From b7284ca20e3c2f27cfc516c6c7b3eeaccfc00d17 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Tue, 26 Jul 2016 09:49:25 -0700 Subject: [PATCH] 8162396: j.u.c java.lang.LinkageError Reviewed-by: martin, psandoz, plevart --- .../util/concurrent/atomic/AtomicInteger.java | 58 ++++++++++-------- .../util/concurrent/atomic/AtomicLong.java | 61 +++++++++++-------- 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java index a6221a86a80..fa7af454788 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -35,7 +35,6 @@ package java.util.concurrent.atomic; -import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.function.IntBinaryOperator; import java.util.function.IntUnaryOperator; @@ -54,11 +53,18 @@ import java.util.function.IntUnaryOperator; */ public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; - private static final VarHandle VALUE; + + /* + * This class intended to be implemented using VarHandles, but there + * are unresolved cyclic startup dependencies. + */ + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); + private static final long VALUE; + static { try { - MethodHandles.Lookup l = MethodHandles.lookup(); - VALUE = l.findVarHandle(AtomicInteger.class, "value", int.class); + VALUE = U.objectFieldOffset + (AtomicInteger.class.getDeclaredField("value")); } catch (ReflectiveOperationException e) { throw new Error(e); } @@ -109,7 +115,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int newValue) { - VALUE.setRelease(this, newValue); + U.putIntRelease(this, VALUE, newValue); } /** @@ -120,7 +126,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndSet(int newValue) { - return (int)VALUE.getAndSet(this, newValue); + return U.getAndSetInt(this, VALUE, newValue); } /** @@ -134,7 +140,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int expectedValue, int newValue) { - return VALUE.compareAndSet(this, expectedValue, newValue); + return U.compareAndSwapInt(this, VALUE, expectedValue, newValue); } /** @@ -147,7 +153,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return {@code true} if successful */ public final boolean weakCompareAndSet(int expectedValue, int newValue) { - return VALUE.weakCompareAndSet(this, expectedValue, newValue); + return U.weakCompareAndSwapInt(this, VALUE, expectedValue, newValue); } /** @@ -159,7 +165,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndIncrement() { - return (int)VALUE.getAndAdd(this, 1); + return U.getAndAddInt(this, VALUE, 1); } /** @@ -171,7 +177,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndDecrement() { - return (int)VALUE.getAndAdd(this, -1); + return U.getAndAddInt(this, VALUE, -1); } /** @@ -182,7 +188,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndAdd(int delta) { - return (int)VALUE.getAndAdd(this, delta); + return U.getAndAddInt(this, VALUE, delta); } /** @@ -194,7 +200,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the updated value */ public final int incrementAndGet() { - return (int)VALUE.addAndGet(this, 1); + return U.getAndAddInt(this, VALUE, 1) + 1; } /** @@ -206,7 +212,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the updated value */ public final int decrementAndGet() { - return (int)VALUE.addAndGet(this, -1); + return U.getAndAddInt(this, VALUE, -1) - 1; } /** @@ -217,7 +223,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the updated value */ public final int addAndGet(int delta) { - return (int)VALUE.addAndGet(this, delta); + return U.getAndAddInt(this, VALUE, delta) + delta; } /** @@ -373,7 +379,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final int getPlain() { - return (int)VALUE.get(this); + return U.getInt(this, VALUE); } /** @@ -385,7 +391,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final void setPlain(int newValue) { - VALUE.set(this, newValue); + U.putInt(this, VALUE, newValue); } /** @@ -396,7 +402,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final int getOpaque() { - return (int)VALUE.getOpaque(this); + return U.getIntOpaque(this, VALUE); } /** @@ -407,7 +413,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final void setOpaque(int newValue) { - VALUE.setOpaque(this, newValue); + U.putIntOpaque(this, VALUE, newValue); } /** @@ -418,7 +424,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final int getAcquire() { - return (int)VALUE.getAcquire(this); + return U.getIntAcquire(this, VALUE); } /** @@ -429,7 +435,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final void setRelease(int newValue) { - VALUE.setRelease(this, newValue); + U.putIntRelease(this, VALUE, newValue); } /** @@ -445,7 +451,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final int compareAndExchange(int expectedValue, int newValue) { - return (int)VALUE.compareAndExchange(this, expectedValue, newValue); + return U.compareAndExchangeIntVolatile(this, VALUE, expectedValue, newValue); } /** @@ -461,7 +467,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final int compareAndExchangeAcquire(int expectedValue, int newValue) { - return (int)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue); + return U.compareAndExchangeIntAcquire(this, VALUE, expectedValue, newValue); } /** @@ -477,7 +483,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final int compareAndExchangeRelease(int expectedValue, int newValue) { - return (int)VALUE.compareAndExchangeRelease(this, expectedValue, newValue); + return U.compareAndExchangeIntRelease(this, VALUE, expectedValue, newValue); } /** @@ -492,7 +498,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final boolean weakCompareAndSetVolatile(int expectedValue, int newValue) { - return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue); + return U.weakCompareAndSwapIntVolatile(this, VALUE, expectedValue, newValue); } /** @@ -507,7 +513,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final boolean weakCompareAndSetAcquire(int expectedValue, int newValue) { - return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue); + return U.weakCompareAndSwapIntAcquire(this, VALUE, expectedValue, newValue); } /** @@ -522,7 +528,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @since 9 */ public final boolean weakCompareAndSetRelease(int expectedValue, int newValue) { - return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue); + return U.weakCompareAndSwapIntRelease(this, VALUE, expectedValue, newValue); } } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java index 2c79beaadae..726e7a3b7e3 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -35,7 +35,6 @@ package java.util.concurrent.atomic; -import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.function.LongBinaryOperator; import java.util.function.LongUnaryOperator; @@ -54,7 +53,6 @@ import java.util.function.LongUnaryOperator; */ public class AtomicLong extends Number implements java.io.Serializable { private static final long serialVersionUID = 1927816293512124184L; - private static final VarHandle VALUE; /** * Records whether the underlying JVM supports lockless @@ -70,10 +68,17 @@ public class AtomicLong extends Number implements java.io.Serializable { */ private static native boolean VMSupportsCS8(); + /* + * This class intended to be implemented using VarHandles, but there + * are unresolved cyclic startup dependencies. + */ + private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); + private static final long VALUE; + static { try { - MethodHandles.Lookup l = MethodHandles.lookup(); - VALUE = l.findVarHandle(AtomicLong.class, "value", long.class); + VALUE = U.objectFieldOffset + (AtomicLong.class.getDeclaredField("value")); } catch (ReflectiveOperationException e) { throw new Error(e); } @@ -113,7 +118,9 @@ public class AtomicLong extends Number implements java.io.Serializable { * @param newValue the new value */ public final void set(long newValue) { - VALUE.setVolatile(this, newValue); + // Use putLongVolatile instead of ordinary volatile store when + // using compareAndSwapLong, for sake of some 32bit systems. + U.putLongVolatile(this, VALUE, newValue); } /** @@ -124,7 +131,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 1.6 */ public final void lazySet(long newValue) { - VALUE.setRelease(this, newValue); + U.putLongRelease(this, VALUE, newValue); } /** @@ -135,7 +142,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndSet(long newValue) { - return (long)VALUE.getAndSet(this, newValue); + return U.getAndSetLong(this, VALUE, newValue); } /** @@ -149,7 +156,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(long expectedValue, long newValue) { - return VALUE.compareAndSet(this, expectedValue, newValue); + return U.compareAndSwapLong(this, VALUE, expectedValue, newValue); } /** @@ -162,7 +169,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return {@code true} if successful */ public final boolean weakCompareAndSet(long expectedValue, long newValue) { - return VALUE.weakCompareAndSet(this, expectedValue, newValue); + return U.weakCompareAndSwapLong(this, VALUE, expectedValue, newValue); } /** @@ -174,7 +181,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndIncrement() { - return (long)VALUE.getAndAdd(this, 1L); + return U.getAndAddLong(this, VALUE, 1L); } /** @@ -186,7 +193,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndDecrement() { - return (long)VALUE.getAndAdd(this, -1L); + return U.getAndAddLong(this, VALUE, -1L); } /** @@ -197,7 +204,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndAdd(long delta) { - return (long)VALUE.getAndAdd(this, delta); + return U.getAndAddLong(this, VALUE, delta); } /** @@ -209,7 +216,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the updated value */ public final long incrementAndGet() { - return (long)VALUE.addAndGet(this, 1L); + return U.getAndAddLong(this, VALUE, 1L) + 1L; } /** @@ -221,7 +228,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the updated value */ public final long decrementAndGet() { - return (long)VALUE.addAndGet(this, -1L); + return U.getAndAddLong(this, VALUE, -1L) - 1L; } /** @@ -232,7 +239,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the updated value */ public final long addAndGet(long delta) { - return (long)VALUE.addAndGet(this, delta); + return U.getAndAddLong(this, VALUE, delta) + delta; } /** @@ -386,7 +393,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final long getPlain() { - return (long)VALUE.get(this); + return U.getLong(this, VALUE); } /** @@ -398,7 +405,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final void setPlain(long newValue) { - VALUE.set(this, newValue); + U.putLong(this, VALUE, newValue); } /** @@ -409,7 +416,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final long getOpaque() { - return (long)VALUE.getOpaque(this); + return U.getLongOpaque(this, VALUE); } /** @@ -420,7 +427,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final void setOpaque(long newValue) { - VALUE.setOpaque(this, newValue); + U.putLongOpaque(this, VALUE, newValue); } /** @@ -431,7 +438,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final long getAcquire() { - return (long)VALUE.getAcquire(this); + return U.getLongAcquire(this, VALUE); } /** @@ -442,7 +449,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final void setRelease(long newValue) { - VALUE.setRelease(this, newValue); + U.putLongRelease(this, VALUE, newValue); } /** @@ -458,7 +465,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final long compareAndExchange(long expectedValue, long newValue) { - return (long)VALUE.compareAndExchange(this, expectedValue, newValue); + return U.compareAndExchangeLongVolatile(this, VALUE, expectedValue, newValue); } /** @@ -474,7 +481,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final long compareAndExchangeAcquire(long expectedValue, long newValue) { - return (long)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue); + return U.compareAndExchangeLongAcquire(this, VALUE, expectedValue, newValue); } /** @@ -490,7 +497,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final long compareAndExchangeRelease(long expectedValue, long newValue) { - return (long)VALUE.compareAndExchangeRelease(this, expectedValue, newValue); + return U.compareAndExchangeLongRelease(this, VALUE, expectedValue, newValue); } /** @@ -505,7 +512,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final boolean weakCompareAndSetVolatile(long expectedValue, long newValue) { - return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue); + return U.weakCompareAndSwapLongVolatile(this, VALUE, expectedValue, newValue); } /** @@ -520,7 +527,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final boolean weakCompareAndSetAcquire(long expectedValue, long newValue) { - return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue); + return U.weakCompareAndSwapLongAcquire(this, VALUE, expectedValue, newValue); } /** @@ -535,7 +542,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @since 9 */ public final boolean weakCompareAndSetRelease(long expectedValue, long newValue) { - return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue); + return U.weakCompareAndSwapLongRelease(this, VALUE, expectedValue, newValue); } }