This is an automated email from the ASF dual-hosted git repository.

fanningpj pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git


The following commit(s) were added to refs/heads/main by this push:
     new db60119b42 avoid sun.misc.Unsafe by using VarHandles (#1990)
db60119b42 is described below

commit db60119b42a959fc578e88f3add5eaf865bb7411
Author: PJ Fanning <[email protected]>
AuthorDate: Sat Aug 2 12:10:52 2025 +0100

    avoid sun.misc.Unsafe by using VarHandles (#1990)
    
    * don't use unsafe to update nextName
    
    Update Children.scala
    
    Update Children.scala
    
    use varhandle
    
    Update AbstractActorCell.java
    
    review comment
    
    Update Children.scala
    
    remove more usages of Unsafe
    
    more
    
    more
    
    more
    
    javafmt
    
    Update LightArrayRevolverScheduler.scala
    
    Update AbstractNodeQueue.java
    
    Update AbstractBoundedNodeQueue.java
    
    Revert "more"
    
    This reverts commit ef119f4ebf9fa528a880dd13dd833e4e8c6effc8.
    
    revert some promise actor changes
    
    javafmt
    
    * watchedBy
    
    * Reapply "more"
    
    This reverts commit ba2b43cd7d920a67e2e3ac9355c50c6b8169d451.
    
    try again
    
    * remove imports
    
    * javafmt
    
    * Update Unsafe.java
    
    * Create util-unsafe-refactor.excludes
    
    * internal api
---
 .../org/apache/pekko/actor/AbstractActorRef.java   | 22 +++++++------
 .../pekko/actor/dungeon/AbstractActorCell.java     | 36 +++++++++++----------
 .../pekko/dispatch/AbstractBoundedNodeQueue.java   | 37 ++++++++++++----------
 .../pekko/dispatch/AbstractMessageDispatcher.java  | 19 ++++++++---
 .../apache/pekko/dispatch/AbstractNodeQueue.java   | 33 +++++++++++--------
 .../pekko/pattern/AbstractCircuitBreaker.java      | 27 ++++++++++------
 .../pekko/pattern/AbstractPromiseActorRef.java     | 23 ++++++++------
 .../main/java/org/apache/pekko/util/Unsafe.java    |  2 +-
 .../util-unsafe-refactor.excludes                  | 19 +++++++++++
 .../pekko/actor/LightArrayRevolverScheduler.scala  | 13 ++++----
 .../apache/pekko/actor/RepointableActorRef.scala   | 13 ++++----
 .../org/apache/pekko/actor/dungeon/Children.scala  | 29 +++++++----------
 .../org/apache/pekko/actor/dungeon/Dispatch.scala  |  7 ++--
 .../apache/pekko/dispatch/AbstractDispatcher.scala | 12 +++----
 .../org/apache/pekko/pattern/AskSupport.scala      | 24 ++++++--------
 .../org/apache/pekko/pattern/CircuitBreaker.scala  | 28 +++++++---------
 .../pekko/remote/artery/AbstractAssociation.java   | 13 +++++---
 .../apache/pekko/remote/artery/Association.scala   |  9 ++----
 18 files changed, 203 insertions(+), 163 deletions(-)

diff --git a/actor/src/main/java/org/apache/pekko/actor/AbstractActorRef.java 
b/actor/src/main/java/org/apache/pekko/actor/AbstractActorRef.java
index dc7ae0413c..7d7eeac66a 100644
--- a/actor/src/main/java/org/apache/pekko/actor/AbstractActorRef.java
+++ b/actor/src/main/java/org/apache/pekko/actor/AbstractActorRef.java
@@ -13,20 +13,24 @@
 
 package org.apache.pekko.actor;
 
-import org.apache.pekko.util.Unsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+import org.apache.pekko.actor.Cell;
 
 final class AbstractActorRef {
-  static final long cellOffset;
-  static final long lookupOffset;
+  static final VarHandle cellHandle;
+  static final VarHandle lookupHandle;
 
   static {
     try {
-      cellOffset =
-          Unsafe.instance.objectFieldOffset(
-              
RepointableActorRef.class.getDeclaredField("_cellDoNotCallMeDirectly"));
-      lookupOffset =
-          Unsafe.instance.objectFieldOffset(
-              
RepointableActorRef.class.getDeclaredField("_lookupDoNotCallMeDirectly"));
+      MethodHandles.Lookup lookup =
+          MethodHandles.privateLookupIn(RepointableActorRef.class, 
MethodHandles.lookup());
+
+      cellHandle =
+          lookup.findVarHandle(RepointableActorRef.class, 
"_cellDoNotCallMeDirectly", Cell.class);
+      lookupHandle =
+          lookup.findVarHandle(RepointableActorRef.class, 
"_lookupDoNotCallMeDirectly", Cell.class);
     } catch (Throwable t) {
       throw new ExceptionInInitializerError(t);
     }
diff --git 
a/actor/src/main/java/org/apache/pekko/actor/dungeon/AbstractActorCell.java 
b/actor/src/main/java/org/apache/pekko/actor/dungeon/AbstractActorCell.java
index 3d4b867900..c7cd1410ec 100644
--- a/actor/src/main/java/org/apache/pekko/actor/dungeon/AbstractActorCell.java
+++ b/actor/src/main/java/org/apache/pekko/actor/dungeon/AbstractActorCell.java
@@ -17,35 +17,39 @@ import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
 
 import org.apache.pekko.actor.ActorCell;
-import org.apache.pekko.util.Unsafe;
+import org.apache.pekko.dispatch.Mailbox;
 
 final class AbstractActorCell {
-  static final long mailboxOffset;
-  static final long childrenOffset;
+  static final VarHandle mailboxHandle;
+  static final VarHandle childrenHandle;
   static final VarHandle nextNameHandle;
-  static final long functionRefsOffset;
+  static final VarHandle functionRefsHandle;
 
   static {
     try {
-      mailboxOffset =
-          Unsafe.instance.objectFieldOffset(
-              ActorCell.class.getDeclaredField(
-                  
"org$apache$pekko$actor$dungeon$Dispatch$$_mailboxDoNotCallMeDirectly"));
-      childrenOffset =
-          Unsafe.instance.objectFieldOffset(
-              ActorCell.class.getDeclaredField(
-                  
"org$apache$pekko$actor$dungeon$Children$$_childrenRefsDoNotCallMeDirectly"));
-      functionRefsOffset =
-          Unsafe.instance.objectFieldOffset(
-              ActorCell.class.getDeclaredField(
-                  
"org$apache$pekko$actor$dungeon$Children$$_functionRefsDoNotCallMeDirectly"));
       MethodHandles.Lookup lookup =
           MethodHandles.privateLookupIn(ActorCell.class, 
MethodHandles.lookup());
+      mailboxHandle =
+          lookup.findVarHandle(
+              ActorCell.class,
+              
"org$apache$pekko$actor$dungeon$Dispatch$$_mailboxDoNotCallMeDirectly",
+              Mailbox.class);
+      childrenHandle =
+          lookup.findVarHandle(
+              ActorCell.class,
+              
"org$apache$pekko$actor$dungeon$Children$$_childrenRefsDoNotCallMeDirectly",
+              ChildrenContainer.class);
       nextNameHandle =
           lookup.findVarHandle(
               ActorCell.class,
               
"org$apache$pekko$actor$dungeon$Children$$_nextNameDoNotCallMeDirectly",
               long.class);
+      functionRefsHandle =
+          lookup.findVarHandle(
+              ActorCell.class,
+              
"org$apache$pekko$actor$dungeon$Children$$_functionRefsDoNotCallMeDirectly",
+              scala.collection.immutable.Map.class);
+
     } catch (Throwable t) {
       throw new ExceptionInInitializerError(t);
     }
diff --git 
a/actor/src/main/java/org/apache/pekko/dispatch/AbstractBoundedNodeQueue.java 
b/actor/src/main/java/org/apache/pekko/dispatch/AbstractBoundedNodeQueue.java
index 3ee85c929f..361fa052e4 100644
--- 
a/actor/src/main/java/org/apache/pekko/dispatch/AbstractBoundedNodeQueue.java
+++ 
b/actor/src/main/java/org/apache/pekko/dispatch/AbstractBoundedNodeQueue.java
@@ -13,7 +13,8 @@
 
 package org.apache.pekko.dispatch;
 
-import org.apache.pekko.util.Unsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 
 /**
  * Lock-free bounded non-blocking multiple-producer single-consumer queue 
based on the works of:
@@ -45,29 +46,27 @@ public abstract class AbstractBoundedNodeQueue<T> {
     }
 
     private void setEnq(Node<T> n) {
-        Unsafe.instance.putObjectVolatile(this, enqOffset, n);
+        enqHandle.set(this, n);
     }
 
-    @SuppressWarnings("unchecked")
     private Node<T> getEnq() {
-        return (Node<T>)Unsafe.instance.getObjectVolatile(this, enqOffset);
+        return (Node<T>) enqHandle.get(this);
     }
 
     private boolean casEnq(Node<T> old, Node<T> nju) {
-        return Unsafe.instance.compareAndSwapObject(this, enqOffset, old, nju);
+        return enqHandle.compareAndSet(this, old, nju);
     }
 
     private void setDeq(Node<T> n) {
-        Unsafe.instance.putObjectVolatile(this, deqOffset, n);
+        deqHandle.set(this, n);
     }
 
-    @SuppressWarnings("unchecked")
     private Node<T> getDeq() {
-        return (Node<T>)Unsafe.instance.getObjectVolatile(this, deqOffset);
+        return (Node<T>) deqHandle.get(this);
     }
 
     private boolean casDeq(Node<T> old, Node<T> nju) {
-        return Unsafe.instance.compareAndSwapObject(this, deqOffset, old, nju);
+        return deqHandle.compareAndSet(this, old, nju);
     }
 
     protected final Node<T> peekNode() {
@@ -183,12 +182,15 @@ public abstract class AbstractBoundedNodeQueue<T> {
         }
     }
 
-    private final static long enqOffset, deqOffset;
+    private final static VarHandle enqHandle, deqHandle;
 
     static {
         try {
-          enqOffset = 
Unsafe.instance.objectFieldOffset(AbstractBoundedNodeQueue.class.getDeclaredField("_enqDoNotCallMeDirectly"));
-          deqOffset = 
Unsafe.instance.objectFieldOffset(AbstractBoundedNodeQueue.class.getDeclaredField("_deqDoNotCallMeDirectly"));
+          MethodHandles.Lookup lookup =
+            MethodHandles.privateLookupIn(AbstractBoundedNodeQueue.class, 
MethodHandles.lookup());
+
+          enqHandle = lookup.findVarHandle(AbstractBoundedNodeQueue.class, 
"_enqDoNotCallMeDirectly", Node.class);
+          deqHandle = lookup.findVarHandle(AbstractBoundedNodeQueue.class, 
"_deqDoNotCallMeDirectly", Node.class);
         } catch(Throwable t){
             throw new ExceptionInInitializerError(t);
         }
@@ -202,18 +204,21 @@ public abstract class AbstractBoundedNodeQueue<T> {
 
         @SuppressWarnings("unchecked")
         public final Node<T> next() {
-            return (Node<T>)Unsafe.instance.getObjectVolatile(this, 
nextOffset);
+            return (Node<T>) nextHandle.get(this);
         }
 
         protected final void setNext(final Node<T> newNext) {
-          Unsafe.instance.putOrderedObject(this, nextOffset, newNext);
+          nextHandle.setRelease(this, newNext);
         }
         
-        private final static long nextOffset;
+        private final static VarHandle nextHandle;
         
         static {
             try {
-                nextOffset = 
Unsafe.instance.objectFieldOffset(Node.class.getDeclaredField("_nextDoNotCallMeDirectly"));
+                MethodHandles.Lookup lookup =
+                  MethodHandles.privateLookupIn(Node.class, 
MethodHandles.lookup());
+
+                nextHandle = lookup.findVarHandle(Node.class, 
"_nextDoNotCallMeDirectly", Node.class);
             } catch(Throwable t){
                 throw new ExceptionInInitializerError(t);
             } 
diff --git 
a/actor/src/main/java/org/apache/pekko/dispatch/AbstractMessageDispatcher.java 
b/actor/src/main/java/org/apache/pekko/dispatch/AbstractMessageDispatcher.java
index 6fafd0dd0f..06093ad041 100644
--- 
a/actor/src/main/java/org/apache/pekko/dispatch/AbstractMessageDispatcher.java
+++ 
b/actor/src/main/java/org/apache/pekko/dispatch/AbstractMessageDispatcher.java
@@ -13,16 +13,25 @@
 
 package org.apache.pekko.dispatch;
 
-import org.apache.pekko.util.Unsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 
 abstract class AbstractMessageDispatcher {
-    final static long shutdownScheduleOffset;
-    final static long inhabitantsOffset;
+    final static VarHandle shutdownScheduleHandle;
+    final static VarHandle inhabitantsHandle;
 
     static {
         try {
-          shutdownScheduleOffset = 
Unsafe.instance.objectFieldOffset(MessageDispatcher.class.getDeclaredField("_shutdownScheduleDoNotCallMeDirectly"));
-          inhabitantsOffset = 
Unsafe.instance.objectFieldOffset(MessageDispatcher.class.getDeclaredField("_inhabitantsDoNotCallMeDirectly"));
+            MethodHandles.Lookup lookup =
+              MethodHandles.privateLookupIn(MessageDispatcher.class, 
MethodHandles.lookup());
+            shutdownScheduleHandle = lookup.findVarHandle(
+                MessageDispatcher.class,
+                "_shutdownScheduleDoNotCallMeDirectly",
+                int.class);
+            inhabitantsHandle = lookup.findVarHandle(
+                MessageDispatcher.class,
+                "_inhabitantsDoNotCallMeDirectly",
+                long.class);
         } catch(Throwable t){
             throw new ExceptionInInitializerError(t);
         }
diff --git 
a/actor/src/main/java/org/apache/pekko/dispatch/AbstractNodeQueue.java 
b/actor/src/main/java/org/apache/pekko/dispatch/AbstractNodeQueue.java
index a67ba9741b..ac8921e155 100644
--- a/actor/src/main/java/org/apache/pekko/dispatch/AbstractNodeQueue.java
+++ b/actor/src/main/java/org/apache/pekko/dispatch/AbstractNodeQueue.java
@@ -13,8 +13,8 @@
 
 package org.apache.pekko.dispatch;
 
-import org.apache.pekko.util.Unsafe;
-
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -54,7 +54,7 @@ public abstract class AbstractNodeQueue<T> extends 
AtomicReference<AbstractNodeQ
      */
     @SuppressWarnings("unchecked")
     protected final Node<T> peekNode() {
-        final Node<T> tail = ((Node<T>)Unsafe.instance.getObjectVolatile(this, 
tailOffset));
+        final Node<T> tail = (Node<T>) tailHandle.get(this);
         Node<T> next = tail.next();
         if (next == null && get() != tail) {
             // if tail != head this is not going to change until producer 
makes progress
@@ -110,7 +110,7 @@ public abstract class AbstractNodeQueue<T> extends 
AtomicReference<AbstractNodeQ
      * @return true if queue was empty at some point in the past
      */
     public final boolean isEmpty() {
-        return Unsafe.instance.getObjectVolatile(this, tailOffset) == get();
+        return tailHandle.get(this) == get();
     }
 
     /**
@@ -126,7 +126,7 @@ public abstract class AbstractNodeQueue<T> extends 
AtomicReference<AbstractNodeQ
     public final int count() {
         int count = 0;
         final Node<T> head = get();
-        for(Node<T> n = ((Node<T>) Unsafe.instance.getObjectVolatile(this, 
tailOffset)).next();
+        for(Node<T> n = ((Node<T>) tailHandle.get(this)).next();
             n != null && count < Integer.MAX_VALUE; 
             n = n.next()) {
           ++count;
@@ -162,7 +162,7 @@ public abstract class AbstractNodeQueue<T> extends 
AtomicReference<AbstractNodeQ
      */
     @SuppressWarnings("unchecked")
     public final Node<T> pollNode() {
-      final Node<T> tail = (Node<T>) Unsafe.instance.getObjectVolatile(this, 
tailOffset);
+      final Node<T> tail = (Node<T>) tailHandle.get(this);
       Node<T> next = tail.next();
       if (next == null && get() != tail) {
           // if tail != head this is not going to change until producer makes 
progress
@@ -175,17 +175,20 @@ public abstract class AbstractNodeQueue<T> extends 
AtomicReference<AbstractNodeQ
       else {
         tail.value = next.value;
         next.value = null;
-        Unsafe.instance.putOrderedObject(this, tailOffset, next);
+        tailHandle.setRelease(this, next);
         tail.setNext(null);
         return tail;
       }
     }
 
-    private final static long tailOffset;
+    private final static VarHandle tailHandle;
 
     static {
         try {
-          tailOffset = 
Unsafe.instance.objectFieldOffset(AbstractNodeQueue.class.getDeclaredField("_tailDoNotCallMeDirectly"));
+          MethodHandles.Lookup lookup =
+            MethodHandles.privateLookupIn(AbstractNodeQueue.class, 
MethodHandles.lookup());
+
+          tailHandle = lookup.findVarHandle(AbstractNodeQueue.class, 
"_tailDoNotCallMeDirectly", Node.class);
         } catch(Throwable t){
             throw new ExceptionInInitializerError(t);
         }
@@ -204,20 +207,22 @@ public abstract class AbstractNodeQueue<T> extends 
AtomicReference<AbstractNodeQ
             this.value = value;
         }
 
-        @SuppressWarnings("unchecked")
         public final Node<T> next() {
-            return (Node<T>)Unsafe.instance.getObjectVolatile(this, 
nextOffset);
+            return (Node<T>) nextHandle.get(this);
         }
 
         protected final void setNext(final Node<T> newNext) {
-          Unsafe.instance.putOrderedObject(this, nextOffset, newNext);
+          nextHandle.setRelease(this, newNext);
         }
         
-        private final static long nextOffset;
+        private final static VarHandle nextHandle;
         
         static {
             try {
-                nextOffset = 
Unsafe.instance.objectFieldOffset(Node.class.getDeclaredField("_nextDoNotCallMeDirectly"));
+                MethodHandles.Lookup lookup =
+                    MethodHandles.privateLookupIn(Node.class, 
MethodHandles.lookup());
+
+                nextHandle = lookup.findVarHandle(Node.class, 
"_nextDoNotCallMeDirectly", Node.class);
             } catch(Throwable t){
                 throw new ExceptionInInitializerError(t);
             } 
diff --git 
a/actor/src/main/java/org/apache/pekko/pattern/AbstractCircuitBreaker.java 
b/actor/src/main/java/org/apache/pekko/pattern/AbstractCircuitBreaker.java
index 13e4874db6..5851d39cb6 100644
--- a/actor/src/main/java/org/apache/pekko/pattern/AbstractCircuitBreaker.java
+++ b/actor/src/main/java/org/apache/pekko/pattern/AbstractCircuitBreaker.java
@@ -13,20 +13,29 @@
 
 package org.apache.pekko.pattern;
 
-import org.apache.pekko.util.Unsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+import scala.concurrent.duration.FiniteDuration;
+
+import org.apache.pekko.pattern.CircuitBreaker.State;
 
 class AbstractCircuitBreaker {
-  protected static final long stateOffset;
-  protected static final long resetTimeoutOffset;
+  protected static final VarHandle stateHandle;
+  protected static final VarHandle resetTimeoutHandle;
 
   static {
     try {
-      stateOffset =
-          Unsafe.instance.objectFieldOffset(
-              
CircuitBreaker.class.getDeclaredField("_currentStateDoNotCallMeDirectly"));
-      resetTimeoutOffset =
-          Unsafe.instance.objectFieldOffset(
-              
CircuitBreaker.class.getDeclaredField("_currentResetTimeoutDoNotCallMeDirectly"));
+      MethodHandles.Lookup lookup =
+          MethodHandles.privateLookupIn(CircuitBreaker.class, 
MethodHandles.lookup());
+      stateHandle =
+          lookup.findVarHandle(
+              CircuitBreaker.class, "_currentStateDoNotCallMeDirectly", 
State.class);
+      resetTimeoutHandle =
+          lookup.findVarHandle(
+              CircuitBreaker.class,
+              "_currentResetTimeoutDoNotCallMeDirectly",
+              FiniteDuration.class);
     } catch (Throwable t) {
       throw new ExceptionInInitializerError(t);
     }
diff --git 
a/actor/src/main/java/org/apache/pekko/pattern/AbstractPromiseActorRef.java 
b/actor/src/main/java/org/apache/pekko/pattern/AbstractPromiseActorRef.java
index f6cf890071..25ec8825f9 100644
--- a/actor/src/main/java/org/apache/pekko/pattern/AbstractPromiseActorRef.java
+++ b/actor/src/main/java/org/apache/pekko/pattern/AbstractPromiseActorRef.java
@@ -13,20 +13,25 @@
 
 package org.apache.pekko.pattern;
 
-import org.apache.pekko.util.Unsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 
 final class AbstractPromiseActorRef {
-  static final long stateOffset;
-  static final long watchedByOffset;
+  static final VarHandle stateHandle;
+  static final VarHandle watchedByHandle;
 
   static {
     try {
-      stateOffset =
-          Unsafe.instance.objectFieldOffset(
-              
PromiseActorRef.class.getDeclaredField("_stateDoNotCallMeDirectly"));
-      watchedByOffset =
-          Unsafe.instance.objectFieldOffset(
-              
PromiseActorRef.class.getDeclaredField("_watchedByDoNotCallMeDirectly"));
+      MethodHandles.Lookup lookup =
+          MethodHandles.privateLookupIn(PromiseActorRef.class, 
MethodHandles.lookup());
+
+      stateHandle =
+          lookup.findVarHandle(PromiseActorRef.class, 
"_stateDoNotCallMeDirectly", Object.class);
+      watchedByHandle =
+          lookup.findVarHandle(
+              PromiseActorRef.class,
+              "_watchedByDoNotCallMeDirectly",
+              scala.collection.immutable.Set.class);
     } catch (Throwable t) {
       throw new ExceptionInInitializerError(t);
     }
diff --git a/actor/src/main/java/org/apache/pekko/util/Unsafe.java 
b/actor/src/main/java/org/apache/pekko/util/Unsafe.java
index faaf820d3c..535d84cac2 100644
--- a/actor/src/main/java/org/apache/pekko/util/Unsafe.java
+++ b/actor/src/main/java/org/apache/pekko/util/Unsafe.java
@@ -21,7 +21,7 @@ import java.nio.charset.StandardCharsets;
 /** INTERNAL API */
 @InternalApi
 public final class Unsafe {
-  public static final sun.misc.Unsafe instance;
+  private static final sun.misc.Unsafe instance;
 
   private static final long stringValueFieldOffset;
   private static final int copyUSAsciiStrToBytesAlgorithm;
diff --git 
a/actor/src/main/mima-filters/2.0.x.backwards.excludes/util-unsafe-refactor.excludes
 
b/actor/src/main/mima-filters/2.0.x.backwards.excludes/util-unsafe-refactor.excludes
new file mode 100644
index 0000000000..abc7d41e41
--- /dev/null
+++ 
b/actor/src/main/mima-filters/2.0.x.backwards.excludes/util-unsafe-refactor.excludes
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Switch to VarHandles means that we don't need Unsafe.instance to be 
accessible
+ProblemFilters.exclude[MissingFieldProblem]("org.apache.pekko.util.Unsafe.instance")
diff --git 
a/actor/src/main/scala/org/apache/pekko/actor/LightArrayRevolverScheduler.scala 
b/actor/src/main/scala/org/apache/pekko/actor/LightArrayRevolverScheduler.scala
index 2f05d48680..eb947e5124 100644
--- 
a/actor/src/main/scala/org/apache/pekko/actor/LightArrayRevolverScheduler.scala
+++ 
b/actor/src/main/scala/org/apache/pekko/actor/LightArrayRevolverScheduler.scala
@@ -14,10 +14,11 @@
 package org.apache.pekko.actor
 
 import java.io.Closeable
+import java.lang.invoke.{ MethodHandles, VarHandle }
 import java.util.concurrent.ThreadFactory
 import java.util.concurrent.atomic.{ AtomicLong, AtomicReference }
 
-import scala.annotation.{ nowarn, tailrec }
+import scala.annotation.tailrec
 import scala.collection.immutable
 import scala.concurrent.{ Await, ExecutionContext, Future, Promise }
 import scala.concurrent.duration._
@@ -29,7 +30,6 @@ import pekko.actor.Scheduler.AtomicCancellable
 import pekko.dispatch.AbstractNodeQueue
 import pekko.event.LoggingAdapter
 import pekko.util.Helpers
-import pekko.util.Unsafe.{ instance => unsafe }
 
 /**
  * This scheduler implementation is based on a revolving wheel of buckets,
@@ -355,9 +355,10 @@ class LightArrayRevolverScheduler(config: Config, log: 
LoggingAdapter, threadFac
 }
 
 object LightArrayRevolverScheduler {
-  @nowarn("msg=deprecated")
-  private[this] val taskOffset =
-    unsafe.objectFieldOffset(classOf[TaskHolder].getDeclaredField("task")): 
@nowarn("cat=deprecation")
+  private[this] val taskHandle: VarHandle = {
+    val lookup = MethodHandles.privateLookupIn(classOf[TaskHolder], 
MethodHandles.lookup())
+    lookup.findVarHandle(classOf[TaskHolder], "task", classOf[Runnable])
+  }
 
   private class TaskQueue extends AbstractNodeQueue[TaskHolder]
 
@@ -376,7 +377,7 @@ object LightArrayRevolverScheduler {
     private final def extractTask(replaceWith: Runnable): Runnable =
       task match {
         case t @ (ExecutedTask | CancelledTask) => t
-        case x                                  => if 
(unsafe.compareAndSwapObject(this, taskOffset, x, replaceWith): 
@nowarn("cat=deprecation")) x
+        case x                                  => if 
(taskHandle.compareAndSet(this, x, replaceWith)) x
           else extractTask(replaceWith)
       }
 
diff --git 
a/actor/src/main/scala/org/apache/pekko/actor/RepointableActorRef.scala 
b/actor/src/main/scala/org/apache/pekko/actor/RepointableActorRef.scala
index 1093ec5379..96e821812d 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/RepointableActorRef.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/RepointableActorRef.scala
@@ -27,7 +27,7 @@ import pekko.actor.dungeon.ChildrenContainer
 import pekko.dispatch._
 import pekko.dispatch.sysmsg._
 import pekko.event.Logging.Warning
-import pekko.util.{ unused, Unsafe }
+import pekko.util.unused
 
 /**
  * This actor ref starts out with some dummy cell (by default just enqueuing
@@ -47,7 +47,7 @@ private[pekko] class RepointableActorRef(
     extends ActorRefWithCell
     with RepointableRef {
 
-  import AbstractActorRef.{ cellOffset, lookupOffset }
+  import AbstractActorRef.{ cellHandle, lookupHandle }
 
   /*
    * H E R E   B E   D R A G O N S !
@@ -66,20 +66,19 @@ private[pekko] class RepointableActorRef(
     _lookupDoNotCallMeDirectly
   }
 
-  def underlying: Cell =
-    Unsafe.instance.getObjectVolatile(this, cellOffset).asInstanceOf[Cell]: 
@nowarn("cat=deprecation")
-  def lookup = Unsafe.instance.getObjectVolatile(this, 
lookupOffset).asInstanceOf[Cell]: @nowarn("cat=deprecation")
+  def underlying: Cell = cellHandle.get(this)
+  def lookup: Cell = lookupHandle.get(this)
 
   @tailrec
   final def swapCell(next: Cell): Cell = {
     val old = underlying
-    if (Unsafe.instance.compareAndSwapObject(this, cellOffset, old, next): 
@nowarn("cat=deprecation")) old
+    if (cellHandle.compareAndSet(this, old, next)) old
     else swapCell(next)
   }
 
   @tailrec final def swapLookup(next: Cell): Cell = {
     val old = lookup
-    if (Unsafe.instance.compareAndSwapObject(this, lookupOffset, old, next): 
@nowarn("cat=deprecation")) old
+    if (lookupHandle.compareAndSet(this, old, next)) old
     else swapLookup(next)
   }
 
diff --git a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala 
b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala
index 37beef6073..02b6d0ed4b 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Children.scala
@@ -23,7 +23,7 @@ import org.apache.pekko
 import pekko.actor._
 import pekko.annotation.InternalStableApi
 import pekko.serialization.{ Serialization, SerializationExtension, 
Serializers }
-import pekko.util.{ Helpers, Unsafe }
+import pekko.util.Helpers
 
 private[pekko] object Children {
   val GetNobody = () => Nobody
@@ -38,11 +38,9 @@ private[pekko] trait Children { this: ActorCell =>
   private var _childrenRefsDoNotCallMeDirectly: ChildrenContainer = 
EmptyChildrenContainer
 
   def childrenRefs: ChildrenContainer =
-    Unsafe.instance.getObjectVolatile(this, 
AbstractActorCell.childrenOffset).asInstanceOf[ChildrenContainer]: @nowarn(
-      "cat=deprecation")
+    AbstractActorCell.childrenHandle.get(this)
 
   final def children: immutable.Iterable[ActorRef] = childrenRefs.children
-  @nowarn("msg=deprecated")
   final def getChildren(): java.lang.Iterable[ActorRef] = {
     import pekko.util.ccompat.JavaConverters._
     children.asJava
@@ -64,10 +62,9 @@ private[pekko] trait Children { this: ActorCell =>
   private[pekko] def attachChild(props: Props, name: String, systemService: 
Boolean): ActorRef =
     makeChild(this, props, checkName(name), async = true, systemService = 
systemService)
 
-  @nowarn @volatile private var _functionRefsDoNotCallMeDirectly = 
Map.empty[String, FunctionRef]
+  @nowarn @volatile private var _functionRefsDoNotCallMeDirectly = 
immutable.Map.empty[String, FunctionRef]
   private def functionRefs: Map[String, FunctionRef] =
-    Unsafe.instance.getObjectVolatile(this, 
AbstractActorCell.functionRefsOffset).asInstanceOf[Map[String,
-      FunctionRef]]: @nowarn("cat=deprecation")
+    AbstractActorCell.functionRefsHandle.get(this)
 
   private[pekko] def getFunctionRefOrNobody(name: String, uid: Int = 
ActorCell.undefinedUid): InternalActorRef =
     functionRefs.getOrElse(name, Children.GetNobody()) match {
@@ -86,8 +83,7 @@ private[pekko] trait Children { this: ActorCell =>
     @tailrec def rec(): Unit = {
       val old = functionRefs
       val added = old.updated(childPath.name, ref)
-      if (!Unsafe.instance.compareAndSwapObject(this, 
AbstractActorCell.functionRefsOffset, old, added): @nowarn(
-          "cat=deprecation")) rec()
+      if (!AbstractActorCell.functionRefsHandle.compareAndSet(this, old, 
added)) rec()
     }
     rec()
 
@@ -102,8 +98,7 @@ private[pekko] trait Children { this: ActorCell =>
       if (!old.contains(name)) false
       else {
         val removed = old - name
-        if (!Unsafe.instance.compareAndSwapObject(this, 
AbstractActorCell.functionRefsOffset, old, removed): @nowarn(
-            "cat=deprecation")) rec()
+        if (!AbstractActorCell.functionRefsHandle.compareAndSet(this, old, 
removed)) rec()
         else {
           ref.stop()
           true
@@ -114,9 +109,9 @@ private[pekko] trait Children { this: ActorCell =>
   }
 
   protected def stopFunctionRefs(): Unit = {
-    val refs = Unsafe.instance
-      .getAndSetObject(this, AbstractActorCell.functionRefsOffset, Map.empty)
-      .asInstanceOf[Map[String, FunctionRef]]: @nowarn("cat=deprecation")
+    val refs = AbstractActorCell.functionRefsHandle
+      .getAndSet(this, Map.empty)
+      .asInstanceOf[Map[String, FunctionRef]]
     refs.valuesIterator.foreach(_.stop())
   }
 
@@ -155,8 +150,7 @@ private[pekko] trait Children { this: ActorCell =>
    * low level CAS helpers
    */
   private final def swapChildrenRefs(oldChildren: ChildrenContainer, 
newChildren: ChildrenContainer): Boolean =
-    Unsafe.instance.compareAndSwapObject(this, 
AbstractActorCell.childrenOffset, oldChildren, newChildren): @nowarn(
-      "cat=deprecation")
+    AbstractActorCell.childrenHandle.compareAndSet(this, oldChildren, 
newChildren)
 
   @tailrec final def reserveChild(name: String): Boolean = {
     val c = childrenRefs
@@ -189,8 +183,7 @@ private[pekko] trait Children { this: ActorCell =>
   }
 
   final protected def setTerminated(): Unit =
-    Unsafe.instance.putObjectVolatile(this, AbstractActorCell.childrenOffset, 
TerminatedChildrenContainer): @nowarn(
-      "cat=deprecation")
+    AbstractActorCell.childrenHandle.set(this, TerminatedChildrenContainer)
 
   /*
    * ActorCell-internal API
diff --git a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala 
b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala
index 495b4a782d..0b1dbd88a0 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/dungeon/Dispatch.scala
@@ -31,7 +31,6 @@ import pekko.dispatch.sysmsg._
 import pekko.event.Logging.Error
 import pekko.serialization.{ DisabledJavaSerializer, SerializationExtension, 
Serializers }
 import pekko.serialization.Serialization
-import pekko.util.Unsafe
 
 @SerialVersionUID(1L)
 final case class SerializationCheckFailedException private[dungeon] (msg: 
Object, cause: Throwable)
@@ -53,14 +52,12 @@ private[pekko] trait Dispatch { this: ActorCell =>
   }
 
   final def mailbox: Mailbox =
-    Unsafe.instance.getObjectVolatile(this, 
AbstractActorCell.mailboxOffset).asInstanceOf[Mailbox]: @nowarn(
-      "cat=deprecation")
+    AbstractActorCell.mailboxHandle.get(this)
 
   @tailrec
   final def swapMailbox(newMailbox: Mailbox): Mailbox = {
     val oldMailbox = mailbox
-    if (!Unsafe.instance.compareAndSwapObject(this, 
AbstractActorCell.mailboxOffset, oldMailbox, newMailbox): @nowarn(
-        "cat=deprecation"))
+    if (!AbstractActorCell.mailboxHandle.compareAndSet(this, oldMailbox, 
newMailbox))
       swapMailbox(newMailbox)
     else oldMailbox
   }
diff --git 
a/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala 
b/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala
index dfacb8908b..5a0e98f1d1 100644
--- a/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala
+++ b/actor/src/main/scala/org/apache/pekko/dispatch/AbstractDispatcher.scala
@@ -28,7 +28,7 @@ import pekko.dispatch.affinity.AffinityPoolConfigurator
 import pekko.dispatch.sysmsg._
 import pekko.event.EventStream
 import pekko.event.Logging.{ emptyMDC, Debug, Error, LogEventException, 
Warning }
-import pekko.util.{ unused, Index, Unsafe }
+import pekko.util.{ unused, Index }
 
 import com.typesafe.config.Config
 
@@ -109,7 +109,7 @@ abstract class MessageDispatcher(val configurator: 
MessageDispatcherConfigurator
     with BatchingExecutor
     with ExecutionContextExecutor {
 
-  import AbstractMessageDispatcher.{ inhabitantsOffset, shutdownScheduleOffset 
}
+  import AbstractMessageDispatcher.{ inhabitantsHandle, shutdownScheduleHandle 
}
   import MessageDispatcher._
   import configurator.prerequisites
 
@@ -124,7 +124,7 @@ abstract class MessageDispatcher(val configurator: 
MessageDispatcherConfigurator
   }
 
   private final def addInhabitants(add: Long): Long = {
-    val old = Unsafe.instance.getAndAddLong(this, inhabitantsOffset, add): 
@nowarn("cat=deprecation")
+    val old: Long = inhabitantsHandle.getAndAdd(this, add)
     val ret = old + add
     if (ret < 0) {
       // We haven't succeeded in decreasing the inhabitants yet but the simple 
fact that we're trying to
@@ -136,12 +136,12 @@ abstract class MessageDispatcher(val configurator: 
MessageDispatcherConfigurator
     ret
   }
 
-  final def inhabitants: Long = Unsafe.instance.getLongVolatile(this, 
inhabitantsOffset): @nowarn("cat=deprecation")
+  final def inhabitants: Long = inhabitantsHandle.get(this)
 
   private final def shutdownSchedule: Int =
-    Unsafe.instance.getIntVolatile(this, shutdownScheduleOffset): 
@nowarn("cat=deprecation")
+    shutdownScheduleHandle.get(this)
   private final def updateShutdownSchedule(expect: Int, update: Int): Boolean =
-    Unsafe.instance.compareAndSwapInt(this, shutdownScheduleOffset, expect, 
update): @nowarn("cat=deprecation")
+    shutdownScheduleHandle.compareAndSet(this, expect, update)
 
   /**
    *  Creates and returns a mailbox for the given actor.
diff --git a/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala 
b/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
index 4cbe494124..d784344350 100644
--- a/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
+++ b/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
@@ -16,11 +16,11 @@ package org.apache.pekko.pattern
 import java.net.URLEncoder
 import java.util.concurrent.TimeoutException
 
-import scala.annotation.tailrec
+import scala.annotation.{ nowarn, tailrec }
+import scala.collection.immutable
 import scala.concurrent.{ Future, Promise }
 import scala.language.implicitConversions
 import scala.util.{ Failure, Success }
-import scala.annotation.nowarn
 import scala.util.control.NoStackTrace
 
 import org.apache.pekko
@@ -28,9 +28,7 @@ import pekko.actor._
 import pekko.annotation.{ InternalApi, InternalStableApi }
 import pekko.dispatch.ExecutionContexts
 import pekko.dispatch.sysmsg._
-import pekko.util.{ Timeout, Unsafe }
-import pekko.util.ByteString
-import pekko.util.unused
+import pekko.util.{ unused, ByteString, Timeout }
 
 /**
  * This is what is used to complete a Future that is returned from an ask/? 
call,
@@ -518,7 +516,7 @@ private[pekko] final class PromiseActorRef(
     _mcn: String,
     refPathPrefix: String)
     extends MinimalActorRef {
-  import AbstractPromiseActorRef.{ stateOffset, watchedByOffset }
+  import AbstractPromiseActorRef.{ stateHandle, watchedByHandle }
   import PromiseActorRef._
 
   // This is necessary for weaving the PromiseActorRef into the asked message, 
i.e. the replyTo pattern.
@@ -542,18 +540,17 @@ private[pekko] final class PromiseActorRef(
 
   @volatile
   @nowarn("msg=is never updated")
-  private[this] var _watchedByDoNotCallMeDirectly: Set[ActorRef] = 
ActorCell.emptyActorRefSet
+  private[this] var _watchedByDoNotCallMeDirectly: immutable.Set[ActorRef] = 
ActorCell.emptyActorRefSet
 
   @nowarn private def _preventPrivateUnusedErasure = {
     _stateDoNotCallMeDirectly
     _watchedByDoNotCallMeDirectly
   }
 
-  private[this] def watchedBy: Set[ActorRef] =
-    Unsafe.instance.getObjectVolatile(this, 
watchedByOffset).asInstanceOf[Set[ActorRef]]: @nowarn("cat=deprecation")
+  private[this] def watchedBy: Set[ActorRef] = watchedByHandle.get(this)
 
   private[this] def updateWatchedBy(oldWatchedBy: Set[ActorRef], newWatchedBy: 
Set[ActorRef]): Boolean =
-    Unsafe.instance.compareAndSwapObject(this, watchedByOffset, oldWatchedBy, 
newWatchedBy): @nowarn("cat=deprecation")
+    watchedByHandle.compareAndSet(this, oldWatchedBy, newWatchedBy)
 
   @tailrec // Returns false if the Promise is already completed
   private[this] final def addWatcher(watcher: ActorRef): Boolean = watchedBy 
match {
@@ -573,13 +570,12 @@ private[pekko] final class PromiseActorRef(
     case other => if (!updateWatchedBy(other, null)) clearWatchers() else other
   }
 
-  private[this] def state: AnyRef = Unsafe.instance.getObjectVolatile(this, 
stateOffset): @nowarn("cat=deprecation")
+  private[this] def state: AnyRef = stateHandle.get(this)
 
   private[this] def updateState(oldState: AnyRef, newState: AnyRef): Boolean =
-    Unsafe.instance.compareAndSwapObject(this, stateOffset, oldState, 
newState): @nowarn("cat=deprecation")
+    stateHandle.compareAndSet(this, oldState, newState)
 
-  private[this] def setState(newState: AnyRef): Unit =
-    Unsafe.instance.putObjectVolatile(this, stateOffset, newState): 
@nowarn("cat=deprecation")
+  private[this] def setState(newState: AnyRef): Unit = stateHandle.set(this, 
newState)
 
   override def getParent: InternalActorRef = provider.tempContainer
 
diff --git a/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala 
b/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala
index cd4a130e6b..a0fd3cfee5 100644
--- a/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala
+++ b/actor/src/main/scala/org/apache/pekko/pattern/CircuitBreaker.scala
@@ -30,9 +30,9 @@ import pekko.PekkoException
 import pekko.actor.{ ExtendedActorSystem, Scheduler }
 import pekko.dispatch.ExecutionContexts.parasitic
 import pekko.pattern.internal.{ CircuitBreakerNoopTelemetry, 
CircuitBreakerTelemetry }
+import pekko.annotation.InternalApi
 import pekko.util.FutureConverters._
 import pekko.util.JavaDurationConverters._
-import pekko.util.Unsafe
 
 /**
  * Companion object providing factory methods for Circuit Breaker which runs 
callbacks in caller's thread
@@ -274,41 +274,34 @@ class CircuitBreaker(
   }
 
   /**
-   * Helper method for access to underlying state via Unsafe
+   * Helper method for access to underlying state via VarHandle
    *
    * @param oldState Previous state on transition
    * @param newState Next state on transition
    * @return Whether the previous state matched correctly
    */
   private[this] def swapState(oldState: State, newState: State): Boolean =
-    Unsafe.instance.compareAndSwapObject(this, 
AbstractCircuitBreaker.stateOffset, oldState, newState): @nowarn(
-      "cat=deprecation")
+    AbstractCircuitBreaker.stateHandle.compareAndSet(this, oldState, newState)
 
   /**
-   * Helper method for accessing underlying state via Unsafe
+   * Helper method for accessing underlying state via VarHandle
    *
    * @return Reference to current state
    */
   private[this] def currentState: State =
-    Unsafe.instance.getObjectVolatile(this, 
AbstractCircuitBreaker.stateOffset).asInstanceOf[State]: @nowarn(
-      "cat=deprecation")
+    AbstractCircuitBreaker.stateHandle.get(this)
 
   /**
-   * Helper method for updating the underlying resetTimeout via Unsafe
+   * Helper method for updating the underlying resetTimeout via VarHandle
    */
   private[this] def swapResetTimeout(oldResetTimeout: FiniteDuration, 
newResetTimeout: FiniteDuration): Boolean =
-    Unsafe.instance.compareAndSwapObject(
-      this,
-      AbstractCircuitBreaker.resetTimeoutOffset,
-      oldResetTimeout,
-      newResetTimeout): @nowarn("cat=deprecation")
+    AbstractCircuitBreaker.resetTimeoutHandle.compareAndSet(this, 
oldResetTimeout, newResetTimeout)
 
   /**
-   * Helper method for accessing to the underlying resetTimeout via Unsafe
+   * Helper method for accessing to the underlying resetTimeout via VarHandle
    */
   private[this] def currentResetTimeout: FiniteDuration =
-    Unsafe.instance.getObjectVolatile(this, 
AbstractCircuitBreaker.resetTimeoutOffset).asInstanceOf[
-      FiniteDuration]: @nowarn("cat=deprecation")
+    AbstractCircuitBreaker.resetTimeoutHandle.get(this)
 
   /**
    * Wraps invocations of asynchronous calls that need to be protected.
@@ -777,7 +770,8 @@ class CircuitBreaker(
   /**
    * Internal state abstraction
    */
-  private sealed trait State {
+  @InternalApi
+  private[pattern] sealed trait State {
     private val listeners = new CopyOnWriteArrayList[Runnable]
 
     /**
diff --git 
a/remote/src/main/java/org/apache/pekko/remote/artery/AbstractAssociation.java 
b/remote/src/main/java/org/apache/pekko/remote/artery/AbstractAssociation.java
index 2ee9d60ff4..8c13799f87 100644
--- 
a/remote/src/main/java/org/apache/pekko/remote/artery/AbstractAssociation.java
+++ 
b/remote/src/main/java/org/apache/pekko/remote/artery/AbstractAssociation.java
@@ -13,16 +13,19 @@
 
 package org.apache.pekko.remote.artery;
 
-import org.apache.pekko.util.Unsafe;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 
 class AbstractAssociation {
-  protected static final long sharedStateOffset;
+  protected static final VarHandle sharedStateHandle;
 
   static {
     try {
-      sharedStateOffset =
-          Unsafe.instance.objectFieldOffset(
-              
Association.class.getDeclaredField("_sharedStateDoNotCallMeDirectly"));
+      MethodHandles.Lookup lookup =
+          MethodHandles.privateLookupIn(Association.class, 
MethodHandles.lookup());
+      sharedStateHandle =
+          lookup.findVarHandle(
+              Association.class, "_sharedStateDoNotCallMeDirectly", 
AssociationState.class);
     } catch (Throwable t) {
       throw new ExceptionInInitializerError(t);
     }
diff --git 
a/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala 
b/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala
index 7da5370d0c..48a8d4e44e 100644
--- a/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala
+++ b/remote/src/main/scala/org/apache/pekko/remote/artery/Association.scala
@@ -67,7 +67,6 @@ import pekko.stream.scaladsl.MergeHub
 import pekko.stream.scaladsl.Source
 import pekko.util.OptionVal
 import pekko.util.PrettyDuration._
-import pekko.util.Unsafe
 import pekko.util.WildcardIndex
 import pekko.util.ccompat._
 
@@ -264,22 +263,20 @@ private[remote] class Association(
   private[artery] var _sharedStateDoNotCallMeDirectly: AssociationState = 
AssociationState()
 
   /**
-   * Helper method for access to underlying state via Unsafe
+   * Helper method for access to underlying state via VarHandle
    *
    * @param oldState Previous state
    * @param newState Next state on transition
    * @return Whether the previous state matched correctly
    */
   private[artery] def swapState(oldState: AssociationState, newState: 
AssociationState): Boolean =
-    Unsafe.instance.compareAndSwapObject(this, 
AbstractAssociation.sharedStateOffset, oldState, newState): @nowarn(
-      "cat=deprecation")
+    AbstractAssociation.sharedStateHandle.compareAndSet(this, oldState, 
newState)
 
   /**
    * @return Reference to current shared state
    */
   def associationState: AssociationState =
-    Unsafe.instance.getObjectVolatile(this, 
AbstractAssociation.sharedStateOffset).asInstanceOf[
-      AssociationState]: @nowarn("cat=deprecation")
+    AbstractAssociation.sharedStateHandle.get(this)
 
   def setControlIdleKillSwitch(killSwitch: OptionVal[SharedKillSwitch]): Unit 
= {
     val current = associationState


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to