JDK-6471906 : java.lang.NegativeArraySizeException in tenToThe
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 5.0u8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: sparc
  • Submitted: 2006-09-18
  • Updated: 2013-03-29
  • Resolved: 2013-02-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b77Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
OPERATING SYSTEM(S):
Windows XP

FULL JDK VERSION(S):
java version "1.5.0_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03)
Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode)

DESCRIPTION:
checkScale allows a value of 2147483647 for the scale but when this
is passed into tenToThe, a new char array is created with a size one
larger 'new char[n + 1]' which causes the exception.

import java.math.BigDecimal;

public class d108737 {
    public static void main(String[] args) {
        BigDecimal.ONE.setScale(Integer.MAX_VALUE);
    }
}

- Exact text of any error messages
Output:
Exception in thread "main" java.lang.NegativeArraySizeException
        at java.math.BigDecimal.tenToThe(BigDecimal.java:3117)
        at java.math.BigDecimal.setScale(BigDecimal.java:2300)
        at java.math.BigDecimal.setScale(BigDecimal.java:2348)
        at d108737.main(d108737.java:5)

Comments
BigDecimal.bigTenToThe() might be able to be improved if faster multiplication algorithms for large integers were available.
30-01-2013

New suggested fix: --- a/src/share/classes/java/math/BigDecimal.java Fri Jan 25 12:25:10 2013 -0800 +++ b/src/share/classes/java/math/BigDecimal.java Tue Jan 29 13:23:47 2013 -0800 @@ -3537,13 +3537,25 @@ else return expandBigIntegerTenPowers(n); } - // BigInteger.pow is slow, so make 10**n by constructing a - // BigInteger from a character string (still not very fast) - char tenpow[] = new char[n + 1]; - tenpow[0] = '1'; - for (int i = 1; i <= n; i++) - tenpow[i] = '0'; - return new BigInteger(tenpow,1, tenpow.length); + + if (n < 1024*524288) { + // BigInteger.pow is slow, so make 10**n by constructing a + // BigInteger from a character string (still not very fast) + // which occupies no more than 1GB (!) of memory. + char tenpow[] = new char[n + 1]; + tenpow[0] = '1'; + for (int i = 1; i <= n; i++) { + tenpow[i] = '0'; + } + return new BigInteger(tenpow, 1, tenpow.length); + } + + if ((n & 0x1) == 0x1) { + return BigInteger.TEN.multiply(bigTenToThe(n - 1)); + } else { + BigInteger tmp = bigTenToThe(n/2); + return tmp.multiply(tmp); + } }
30-01-2013

SUGGESTED FIX diff --git a/src/share/classes/java/math/BigDecimal.java b/src/share/classes/java/math/BigDecimal.java --- a/src/share/classes/java/math/BigDecimal.java +++ b/src/share/classes/java/math/BigDecimal.java @@ -3540,11 +3540,17 @@ } // BigInteger.pow is slow, so make 10**n by constructing a // BigInteger from a character string (still not very fast) + + BigInteger multiplier = BigInteger.ONE; + if (n == Integer.MAX_VALUE) { + n--; + multiplier = BigInteger.TEN; + } char tenpow[] = new char[n + 1]; tenpow[0] = '1'; for (int i = 1; i <= n; i++) tenpow[i] = '0'; - return new BigInteger(tenpow,1, tenpow.length); + return multiplier.multiply(new BigInteger(tenpow, 1, tenpow.length)); } /**
02-09-2011

EVALUATION Should be fixed; even extreme values should work.
18-09-2006