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 c11434abb4 remove final use of sun.misc.Unsafe (#1995)
c11434abb4 is described below
commit c11434abb42eb7273593bb307e7654e1c8fc8532
Author: PJ Fanning <[email protected]>
AuthorDate: Thu Aug 7 09:36:46 2025 +0100
remove final use of sun.misc.Unsafe (#1995)
* remove final use of sun.misc.Unsafe
* Update PekkoBuild.scala
* update exception handling
* Update Unsafe.java
---
.../apache/pekko/util/AsciiStringCopySpec.scala | 1 -
.../main/java/org/apache/pekko/util/Unsafe.java | 94 ++++++----------------
project/PekkoBuild.scala | 3 +-
3 files changed, 24 insertions(+), 74 deletions(-)
diff --git
a/actor-tests/src/test/scala/org/apache/pekko/util/AsciiStringCopySpec.scala
b/actor-tests/src/test/scala/org/apache/pekko/util/AsciiStringCopySpec.scala
index 857a0f8ef5..3c35b7549b 100644
--- a/actor-tests/src/test/scala/org/apache/pekko/util/AsciiStringCopySpec.scala
+++ b/actor-tests/src/test/scala/org/apache/pekko/util/AsciiStringCopySpec.scala
@@ -26,7 +26,6 @@ class AsciiStringCopySpec extends AnyWordSpec with Matchers {
// this is known to fail with JDK 11 on ARM32 (Raspberry Pi),
// and therefore algorithm 0 is selected on that architecture
Unsafe.testUSAsciiStrToBytesAlgorithm1("abc") should ===(true)
- Unsafe.testUSAsciiStrToBytesAlgorithm2("abc") should ===(false)
}
"copy string internal representation successfully" in {
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 535d84cac2..2b12522844 100644
--- a/actor/src/main/java/org/apache/pekko/util/Unsafe.java
+++ b/actor/src/main/java/org/apache/pekko/util/Unsafe.java
@@ -15,47 +15,37 @@ package org.apache.pekko.util;
import org.apache.pekko.annotation.InternalApi;
-import java.lang.reflect.Field;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
import java.nio.charset.StandardCharsets;
/** INTERNAL API */
@InternalApi
public final class Unsafe {
- private static final sun.misc.Unsafe instance;
-
- private static final long stringValueFieldOffset;
+ private static final VarHandle stringValueFieldHandle;
private static final int copyUSAsciiStrToBytesAlgorithm;
static {
try {
- sun.misc.Unsafe found = null;
- for (Field field : sun.misc.Unsafe.class.getDeclaredFields()) {
- if (field.getType() == sun.misc.Unsafe.class) {
- field.setAccessible(true);
- found = (sun.misc.Unsafe) field.get(null);
- break;
- }
- }
- if (found == null) throw new IllegalStateException("Can't find instance
of sun.misc.Unsafe");
- else instance = found;
-
- long fo;
+ VarHandle handle;
try {
- fo =
instance.objectFieldOffset(String.class.getDeclaredField("value"));
- } catch (NoSuchFieldException nsfe) {
- // The platform's implementation of String doesn't have a 'value'
field, so we have to use
- // algorithm 0
- fo = -1;
+ MethodHandles.Lookup lookup =
+ MethodHandles.privateLookupIn(String.class,
MethodHandles.lookup());
+ handle = lookup.findVarHandle(String.class, "value", byte[].class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ // The platform's implementation of String doesn't have a 'value' field
+ // or the field is inaccessible, so we have to use algorithm 0.
+ // You need `--add-opens=java.base/java.lang=ALL-UNNAMED` or similar
to access it.
+ handle = null;
}
- stringValueFieldOffset = fo;
+ stringValueFieldHandle = handle;
- if (stringValueFieldOffset > -1) {
- // Select optimization algorithm for `copyUSAciiBytesToStr`.
+ if (handle != null) {
+ // Select optimization algorithm for `copyUSAsciiBytesToStr`.
// For example algorithm 1 will fail with JDK 11 on ARM32 (Raspberry
Pi),
// and therefore algorithm 0 is selected on that architecture.
String testStr = "abc";
if (testUSAsciiStrToBytesAlgorithm1(testStr))
copyUSAsciiStrToBytesAlgorithm = 1;
- else if (testUSAsciiStrToBytesAlgorithm2(testStr))
copyUSAsciiStrToBytesAlgorithm = 2;
else copyUSAsciiStrToBytesAlgorithm = 0;
} else
// We know so little about the platform's String implementation that
we have
@@ -70,12 +60,12 @@ public final class Unsafe {
try {
byte[] bytes = new byte[str.length()];
- // copy of implementation in copyUSAciiBytesToStr
+ // copy of implementation in copyUSAsciiBytesToStr
byte[] strBytes = str.getBytes(StandardCharsets.US_ASCII);
System.arraycopy(strBytes, 0, bytes, 0, str.length());
// end copy
- String result = copyUSAciiBytesToStr(str.length(), bytes);
+ String result = copyUSAsciiBytesToStr(str.length(), bytes);
return str.equals(result);
} catch (Throwable all) {
return false;
@@ -86,38 +76,19 @@ public final class Unsafe {
try {
byte[] bytes = new byte[str.length()];
- // copy of implementation in copyUSAciiBytesToStr
- final byte[] chars = (byte[]) instance.getObject(str,
stringValueFieldOffset);
+ // copy of implementation in copyUSAsciiBytesToStr
+ final byte[] chars = (byte[]) stringValueFieldHandle.get(str);
System.arraycopy(chars, 0, bytes, 0, str.length());
// end copy
- String result = copyUSAciiBytesToStr(str.length(), bytes);
+ String result = copyUSAsciiBytesToStr(str.length(), bytes);
return str.equals(result);
} catch (Throwable all) {
return false;
}
}
- static boolean testUSAsciiStrToBytesAlgorithm2(String str) {
- try {
- byte[] bytes = new byte[str.length()];
-
- // copy of implementation in copyUSAciiBytesToStr
- final char[] chars = (char[]) instance.getObject(str,
stringValueFieldOffset);
- int i = 0;
- while (i < str.length()) {
- bytes[i] = (byte) chars[i++];
- }
- // end copy
-
- String result = copyUSAciiBytesToStr(str.length(), bytes);
- return str.equals(result);
- } catch (Throwable all) {
- return false;
- }
- }
-
- private static String copyUSAciiBytesToStr(int length, byte[] bytes) {
+ private static String copyUSAsciiBytesToStr(int length, byte[] bytes) {
char[] resultChars = new char[length];
int i = 0;
while (i < length) {
@@ -130,14 +101,8 @@ public final class Unsafe {
public static void copyUSAsciiStrToBytes(String str, byte[] bytes) {
if (copyUSAsciiStrToBytesAlgorithm == 1) {
- final byte[] chars = (byte[]) instance.getObject(str,
stringValueFieldOffset);
+ final byte[] chars = (byte[]) stringValueFieldHandle.get(str);
System.arraycopy(chars, 0, bytes, 0, str.length());
- } else if (copyUSAsciiStrToBytesAlgorithm == 2) {
- final char[] chars = (char[]) instance.getObject(str,
stringValueFieldOffset);
- int i = 0;
- while (i < str.length()) {
- bytes[i] = (byte) chars[i++];
- }
} else {
byte[] strBytes = str.getBytes(StandardCharsets.US_ASCII);
System.arraycopy(strBytes, 0, bytes, 0, str.length());
@@ -150,20 +115,7 @@ public final class Unsafe {
int i = 0;
if (copyUSAsciiStrToBytesAlgorithm == 1) {
- final byte[] chars = (byte[]) instance.getObject(str,
stringValueFieldOffset);
- while (i < str.length()) {
- long x = s0 ^ (long) chars[i++]; // Mix character into PRNG state
- long y = s1;
-
- // Xorshift128+ round
- s0 = y;
- x ^= x << 23;
- y ^= y >>> 26;
- x ^= x >>> 17;
- s1 = x ^ y;
- }
- } else if (copyUSAsciiStrToBytesAlgorithm == 2) {
- final char[] chars = (char[]) instance.getObject(str,
stringValueFieldOffset);
+ final byte[] chars = (byte[]) stringValueFieldHandle.get(str);
while (i < str.length()) {
long x = s0 ^ (long) chars[i++]; // Mix character into PRNG state
long y = s1;
diff --git a/project/PekkoBuild.scala b/project/PekkoBuild.scala
index f5cccef539..acc4b31e98 100644
--- a/project/PekkoBuild.scala
+++ b/project/PekkoBuild.scala
@@ -111,8 +111,7 @@ object PekkoBuild {
private val jvmGCLogOptions: Seq[String] = Seq("-Xlog:gc*")
- // -XDignore.symbol.file suppresses sun.misc.Unsafe warnings
- final val DefaultJavacOptions = Seq("-encoding", "UTF-8",
"-Xlint:unchecked", "-XDignore.symbol.file")
+ final val DefaultJavacOptions = Seq("-encoding", "UTF-8", "-Xlint:unchecked")
lazy val defaultSettings: Seq[Setting[_]] = Def.settings(
projectInfoVersion := (if (isSnapshot.value) "snapshot" else
version.value),
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]