From e6e7ac01c7f27d2faac8a90dd7bd78fd88869aba Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 23 Apr 2025 12:05:39 +0200 Subject: [PATCH 1/2] Update ConcurrentSkipListSet, CopyOnWriteArrayList, and AtomicReferenceArray to use Unsafe rather than Field.setAccessible --- .../util/concurrent/ConcurrentSkipListSet.java | 16 ++++++++-------- .../util/concurrent/CopyOnWriteArrayList.java | 15 +++++++-------- .../concurrent/atomic/AtomicReferenceArray.java | 17 ++++++++--------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 649eaa563c7c1..b8d1aaa82a83b 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -35,7 +35,8 @@ package java.util.concurrent; -import java.lang.reflect.Field; +import jdk.internal.misc.Unsafe; + import java.util.AbstractSet; import java.util.Collection; import java.util.Collections; @@ -527,12 +528,11 @@ public Spliterator spliterator() { /** Initializes map field; for use in clone. */ private void setMap(ConcurrentNavigableMap map) { - try { - Field mapField = ConcurrentSkipListSet.class.getDeclaredField("m"); - mapField.setAccessible(true); - mapField.set(this, map); - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new Error(e); - } + final Unsafe U = Unsafe.getUnsafe(); + U.putReference( + this, + U.objectFieldOffset(ConcurrentSkipListSet.class, "m"), + map + ); } } diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 2d3bdb429e948..9024fca802413 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -35,7 +35,6 @@ package java.util.concurrent; import java.lang.invoke.VarHandle; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -57,6 +56,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import jdk.internal.access.SharedSecrets; +import jdk.internal.misc.Unsafe; import jdk.internal.util.ArraysSupport; /** @@ -2095,12 +2095,11 @@ public List reversed() { /** Initializes the lock; for use when deserializing or cloning. */ private void resetLock() { - try { - Field lockField = CopyOnWriteArrayList.class.getDeclaredField("lock"); - lockField.setAccessible(true); - lockField.set(this, new Object()); - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new Error(e); - } + final Unsafe U = Unsafe.getUnsafe(); + U.putReference( + this, + U.objectFieldOffset(CopyOnWriteArrayList.class, "lock"), + new Object() + ); } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index ff4e9fa735552..67315296a8d18 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -35,10 +35,11 @@ package java.util.concurrent.atomic; +import jdk.internal.misc.Unsafe; + import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.util.Arrays; import java.util.function.BinaryOperator; import java.util.function.UnaryOperator; @@ -330,14 +331,13 @@ private void readObject(java.io.ObjectInputStream s) throw new java.io.InvalidObjectException("Not array type"); if (a.getClass() != Object[].class) a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); - try { - Field arrayField = AtomicReferenceArray.class.getDeclaredField("array"); - arrayField.setAccessible(true); - arrayField.set(this, a); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new Error(e); - } + final Unsafe U = Unsafe.getUnsafe(); + U.putReference( + this, + U.objectFieldOffset(AtomicReferenceArray.class, "array"), + a + ); } // jdk9 @@ -523,5 +523,4 @@ public final boolean weakCompareAndSetAcquire(int i, E expectedValue, E newValue public final boolean weakCompareAndSetRelease(int i, E expectedValue, E newValue) { return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue); } - } From 39dba5dc8415bd003df9e5dde0d2a64cac1a89d3 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 23 Apr 2025 17:15:12 +0200 Subject: [PATCH 2/2] Adding a releaseFence() to ConcurrentskipListSet.clone() --- .../classes/java/util/concurrent/ConcurrentSkipListSet.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index b8d1aaa82a83b..0b0db4e8120ff 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -37,6 +37,7 @@ import jdk.internal.misc.Unsafe; +import java.lang.invoke.VarHandle; import java.util.AbstractSet; import java.util.Collection; import java.util.Collections; @@ -177,6 +178,8 @@ public ConcurrentSkipListSet clone() { ConcurrentSkipListSet clone = (ConcurrentSkipListSet) super.clone(); clone.setMap(new ConcurrentSkipListMap(m)); + // Needed to ensure safe publication of setMap() + VarHandle.releaseFence(); return clone; } catch (CloneNotSupportedException e) { throw new InternalError();