Merge "Revert "OpenJDK 11: Merging in java.lang.ref.Cleaner""
diff --git a/api/current.txt b/api/current.txt
index 6b3f9fa..92cb73a 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -3177,8 +3177,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);
@@ -3200,8 +3200,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);
@@ -3253,8 +3255,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);
@@ -3276,8 +3278,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);
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/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
index 08d1aa3..6739605 100644
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -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/Integer.java b/ojluni/src/main/java/java/lang/Integer.java
index 93ae24c..3df8c28 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,7 +1086,7 @@
      * 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 {
@@ -821,7 +1098,7 @@
             // 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);
@@ -861,6 +1138,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 +1158,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 +1176,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 +1213,7 @@
      * Returns the value of this {@code Integer} as an
      * {@code int}.
      */
+    @HotSpotIntrinsicCandidate
     public int intValue() {
         return value;
     }
@@ -983,13 +1273,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;
@@ -1358,7 +1648,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 +1669,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 +1711,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 +1738,7 @@
      *     to zero.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int numberOfTrailingZeros(int i) {
         // HD, Figure 5-14
         int y;
@@ -1476,6 +1761,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 +1835,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 +1862,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/Long.java b/ojluni/src/main/java/java/lang/Long.java
index 0047125..c5f5edd 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
@@ -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/test/java/lang/Integer/ParsingTest.java b/ojluni/src/test/java/lang/Integer/ParsingTest.java
new file mode 100644
index 0000000..e24ba15
--- /dev/null
+++ b/ojluni/src/test/java/lang/Integer/ParsingTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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;
+
+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 {
+            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 {
+            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 {
+            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) {
+        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);
+    }
+}
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..f369ea9
--- /dev/null
+++ b/ojluni/src/test/java/lang/Long/ParsingTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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;
+
+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 {
+            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 {
+            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 {
+            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) {
+        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);
+    }
+}
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..8b4a62b
--- /dev/null
+++ b/ojluni/src/test/java/lang/Long/Unsigned.java
@@ -0,0 +1,410 @@
+/*
+ * 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;
+
+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
+                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())));
+                }
+            }
+        }
+    }
+}