6838776: Defer initialization of static fields in java.math.BigInteger
Reviewed-by: mduigou, mduigou
--- a/jdk/src/share/classes/java/math/BigDecimal.java Mon Sep 05 08:04:04 2011 -0700
+++ b/jdk/src/share/classes/java/math/BigDecimal.java Tue Sep 06 06:17:52 2011 -0700
@@ -3715,26 +3715,28 @@
}
}
- 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 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);
+ }
}
- }
-
- private void setIntCompactVolatile(long val) {
- unsafe.putLongVolatile(this, intCompactOffset, val);
- }
-
- private void setIntValVolatile(BigInteger val) {
- unsafe.putObjectVolatile(this, intValOffset, val);
+ 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 @@
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 @@
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/jdk/src/share/classes/java/math/BigInteger.java Mon Sep 05 08:04:04 2011 -0700
+++ b/jdk/src/share/classes/java/math/BigInteger.java Tue Sep 06 06:17:52 2011 -0700
@@ -3303,25 +3303,35 @@
}
// 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);
}
}