JDK-6838776 : Defer initialization of static fields in java.math.BigInteger
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 6u14
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2009-05-07
  • Updated: 2014-10-10
  • Resolved: 2012-05-14
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 b06Fixed
Related Reports
Relates :  
Relates :  
Description
The fix for 6622432: RFE: Performance improvements to java.math.BigDecimal in 6u14 adds two new static fields that are only needed for deserialization.  Better to initialize them lazily when needed.

    private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
    private static final long signumOffset;
    private static final long magOffset;
    static {
        try {
            signumOffset = unsafe.objectFieldOffset
                (BigInteger.class.getDeclaredField("signum"));
            magOffset = unsafe.objectFieldOffset
                (BigInteger.class.getDeclaredField("mag"));
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }


zeros is another static field used by the toString() method and it can also be lazily initialized.

Comments
SUGGESTED FIX # HG changeset patch # User darcy # Date 1315315072 25200 # Node ID 5077e7a682595499859bb918fab946a69fe409af # Parent 43880d125b790009a73a4f72a97a287f3c2cfaa7 6838776: Defer initialization of static fields in java.math.BigInteger Reviewed-by: mduigou, mduigou --- a/src/share/classes/java/math/BigDecimal.java Mon Sep 05 08:04:04 2011 -0700 +++ b/src/share/classes/java/math/BigDecimal.java Tue Sep 06 06:17:52 2011 -0700 @@ -3715,26 +3715,28 @@ public class BigDecimal extends Number i } } - private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); - private static final long intCompactOffset; - private static final long intValOffset; - static { - try { - intCompactOffset = unsafe.objectFieldOffset - (BigDecimal.class.getDeclaredField("intCompact")); - intValOffset = unsafe.objectFieldOffset - (BigDecimal.class.getDeclaredField("intVal")); - } catch (Exception ex) { - throw new Error(ex); - } - } - - private void setIntCompactVolatile(long val) { - unsafe.putLongVolatile(this, intCompactOffset, val); - } - - private void setIntValVolatile(BigInteger val) { - unsafe.putObjectVolatile(this, intValOffset, val); + private static class UnsafeHolder { + private static final sun.misc.Unsafe unsafe; + private static final long intCompactOffset; + private static final long intValOffset; + static { + try { + unsafe = sun.misc.Unsafe.getUnsafe(); + intCompactOffset = unsafe.objectFieldOffset + (BigDecimal.class.getDeclaredField("intCompact")); + intValOffset = unsafe.objectFieldOffset + (BigDecimal.class.getDeclaredField("intVal")); + } catch (Exception ex) { + throw new ExceptionInInitializerError(ex); + } + } + static void setIntCompactVolatile(BigDecimal bd, long val) { + unsafe.putLongVolatile(bd, intCompactOffset, val); + } + + static void setIntValVolatile(BigDecimal bd, BigInteger val) { + unsafe.putObjectVolatile(bd, intValOffset, val); + } } /** @@ -3753,7 +3755,7 @@ public class BigDecimal extends Number i throw new java.io.StreamCorruptedException(message); // [all values of scale are now allowed] } - setIntCompactVolatile(compactValFor(intVal)); + UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal)); } /** @@ -3765,7 +3767,7 @@ public class BigDecimal extends Number i throws java.io.IOException { // Must inflate to maintain compatible serial form. if (this.intVal == null) - this.setIntValVolatile(BigInteger.valueOf(this.intCompact)); + UnsafeHolder.setIntValVolatile(this, BigInteger.valueOf(this.intCompact)); // Could reset intVal back to null if it has to be set. s.defaultWriteObject(); } --- a/src/share/classes/java/math/BigInteger.java Mon Sep 05 08:04:04 2011 -0700 +++ b/src/share/classes/java/math/BigInteger.java Tue Sep 06 06:17:52 2011 -0700 @@ -3303,25 +3303,35 @@ public class BigInteger extends Number i } // Commit final fields via Unsafe - unsafe.putIntVolatile(this, signumOffset, sign); + UnsafeHolder.putSign(this, sign); // Calculate mag field from magnitude and discard magnitude - unsafe.putObjectVolatile(this, magOffset, - stripLeadingZeroBytes(magnitude)); + UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude)); } // Support for resetting final fields while deserializing - private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); - private static final long signumOffset; - private static final long magOffset; - static { - try { - signumOffset = unsafe.objectFieldOffset - (BigInteger.class.getDeclaredField("signum")); - magOffset = unsafe.objectFieldOffset - (BigInteger.class.getDeclaredField("mag")); - } catch (Exception ex) { - throw new Error(ex); + private static class UnsafeHolder { + private static final sun.misc.Unsafe unsafe; + private static final long signumOffset; + private static final long magOffset; + static { + try { + unsafe = sun.misc.Unsafe.getUnsafe(); + signumOffset = unsafe.objectFieldOffset + (BigInteger.class.getDeclaredField("signum")); + magOffset = unsafe.objectFieldOffset + (BigInteger.class.getDeclaredField("mag")); + } catch (Exception ex) { + throw new ExceptionInInitializerError(ex); + } + } + + static void putSign(BigInteger bi, int sign) { + unsafe.putIntVolatile(bi, signumOffset, sign); + } + + static void putMag(BigInteger bi, int[] magnitude) { + unsafe.putObjectVolatile(bi, magOffset, magnitude); } }
07-09-2011

PUBLIC COMMENTS See http://hg.openjdk.java.net/jdk8/tl/jdk/rev/5077e7a68259
07-09-2011

EVALUATION A fine idea.
03-09-2011

PUBLIC COMMENTS See corelib thread: http://cr.openjdk.java.net/~darcy/6838776.0/
03-09-2011