Skip to content

Commit 661360e

Browse files
committed
Proactively avoid Unsafe on Java 23+
1 parent ded95ea commit 661360e

File tree

2 files changed

+31
-58
lines changed
  • sdk/trace-shaded-deps/src

2 files changed

+31
-58
lines changed

sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
import java.util.Objects;
99
import java.util.Queue;
10-
import java.util.concurrent.ArrayBlockingQueue;
1110
import java.util.concurrent.atomic.AtomicBoolean;
1211
import java.util.function.Consumer;
1312
import java.util.logging.Level;
1413
import java.util.logging.Logger;
1514
import org.jctools.queues.MessagePassingQueue;
1615
import org.jctools.queues.MpscArrayQueue;
16+
import org.jctools.queues.atomic.MpscAtomicArrayQueue;
1717

1818
/**
1919
* Internal accessor of JCTools package for fast queues.
@@ -25,11 +25,15 @@ public final class JcTools {
2525

2626
private static final AtomicBoolean queueCreationWarningLogged = new AtomicBoolean();
2727
private static final Logger logger = Logger.getLogger(JcTools.class.getName());
28+
private static final boolean PROACTIVELY_AVOID_UNSAFE = proactivelyAvoidUnsafe();
2829

2930
/**
3031
* Returns a new {@link Queue} appropriate for use with multiple producers and a single consumer.
3132
*/
3233
public static <T> Queue<T> newFixedSizeQueue(int capacity) {
34+
if (PROACTIVELY_AVOID_UNSAFE) {
35+
return new MpscAtomicArrayQueue<>(capacity);
36+
}
3337
try {
3438
return new MpscArrayQueue<>(capacity);
3539
} catch (java.lang.NoClassDefFoundError | java.lang.ExceptionInInitializerError e) {
@@ -41,7 +45,7 @@ public static <T> Queue<T> newFixedSizeQueue(int capacity) {
4145
}
4246
// Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution,
4347
// or a security manager preventing access to Unsafe is installed.
44-
return new ArrayBlockingQueue<>(capacity);
48+
return new MpscAtomicArrayQueue<>(capacity);
4549
}
4650
}
4751

@@ -50,11 +54,7 @@ public static <T> Queue<T> newFixedSizeQueue(int capacity) {
5054
* to use the shaded classes.
5155
*/
5256
public static long capacity(Queue<?> queue) {
53-
if (queue instanceof MessagePassingQueue) {
54-
return ((MessagePassingQueue<?>) queue).capacity();
55-
} else {
56-
return (long) ((ArrayBlockingQueue<?>) queue).remainingCapacity() + queue.size();
57-
}
57+
return ((MessagePassingQueue<?>) queue).capacity();
5858
}
5959

6060
/**
@@ -65,22 +65,26 @@ public static long capacity(Queue<?> queue) {
6565
*/
6666
@SuppressWarnings("unchecked")
6767
public static <T> int drain(Queue<T> queue, int limit, Consumer<T> consumer) {
68-
if (queue instanceof MessagePassingQueue) {
69-
return ((MessagePassingQueue<T>) queue).drain(consumer::accept, limit);
70-
} else {
71-
return drainNonJcQueue(queue, limit, consumer);
72-
}
68+
return ((MessagePassingQueue<T>) queue).drain(consumer::accept, limit);
7369
}
7470

75-
private static <T> int drainNonJcQueue(
76-
Queue<T> queue, int maxExportBatchSize, Consumer<T> consumer) {
77-
int polledCount = 0;
78-
T item;
79-
while (polledCount < maxExportBatchSize && (item = queue.poll()) != null) {
80-
consumer.accept(item);
81-
++polledCount;
71+
private static boolean proactivelyAvoidUnsafe() {
72+
double javaVersion = getJavaVersion();
73+
// Avoid Unsafe on Java 23+ due to JEP-498 deprecation warnings:
74+
// "WARNING: A terminally deprecated method in sun.misc.Unsafe has been called"
75+
return javaVersion >= 23 || javaVersion == -1;
76+
}
77+
78+
private static double getJavaVersion() {
79+
String specVersion = System.getProperty("java.specification.version");
80+
if (specVersion != null) {
81+
try {
82+
return Double.parseDouble(specVersion);
83+
} catch (NumberFormatException exception) {
84+
// ignore
85+
}
8286
}
83-
return polledCount;
87+
return -1;
8488
}
8589

8690
private JcTools() {}

sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsTest.java

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,19 @@
99

1010
import java.util.ArrayList;
1111
import java.util.Queue;
12-
import java.util.concurrent.ArrayBlockingQueue;
1312
import org.jctools.queues.MpscArrayQueue;
13+
import org.jctools.queues.atomic.MpscAtomicArrayQueue;
1414
import org.junit.jupiter.api.Test;
15-
import org.junit.jupiter.api.extension.ExtendWith;
16-
import org.mockito.junit.jupiter.MockitoExtension;
17-
import org.mockito.junit.jupiter.MockitoSettings;
18-
import org.mockito.quality.Strictness;
1915

20-
@ExtendWith(MockitoExtension.class)
21-
@MockitoSettings(strictness = Strictness.LENIENT)
2216
class JcToolsTest {
2317

2418
ArrayList<String> batch = new ArrayList<>(10);
2519

26-
@Test
27-
void drain_ArrayBlockingQueue() {
28-
// Arrange
29-
batch.add("Test3");
30-
Queue<String> queue = new ArrayBlockingQueue<>(10);
31-
queue.add("Test1");
32-
queue.add("Test2");
33-
34-
// Act
35-
JcTools.drain(queue, 5, batch::add);
36-
37-
// Assert
38-
assertThat(batch).hasSize(3);
39-
assertThat(queue).hasSize(0);
40-
}
41-
4220
@Test
4321
void drain_MessagePassingQueue() {
4422
// Arrange
4523
batch.add("Test3");
46-
Queue<String> queue = new MpscArrayQueue<>(10);
24+
Queue<String> queue = JcTools.newFixedSizeQueue(10);
4725
queue.add("Test1");
4826
queue.add("Test2");
4927

@@ -58,7 +36,7 @@ void drain_MessagePassingQueue() {
5836
@Test
5937
void drain_MaxBatch() {
6038
// Arrange
61-
Queue<String> queue = new MpscArrayQueue<>(10);
39+
Queue<String> queue = JcTools.newFixedSizeQueue(10);
6240
queue.add("Test1");
6341
queue.add("Test2");
6442

@@ -79,7 +57,10 @@ void newFixedSize_MpscQueue() {
7957
Queue<Object> objects = JcTools.newFixedSizeQueue(capacity);
8058

8159
// Assert
82-
assertThat(objects).isInstanceOf(MpscArrayQueue.class);
60+
assertThat(objects)
61+
.satisfiesAnyOf(
62+
queue -> assertThat(queue).isInstanceOf(MpscArrayQueue.class),
63+
queue -> assertThat(queue).isInstanceOf(MpscAtomicArrayQueue.class));
8364
}
8465

8566
@Test
@@ -94,16 +75,4 @@ void capacity_MpscQueue() {
9475
// Assert
9576
assertThat(queueSize).isGreaterThan(capacity);
9677
}
97-
98-
@Test
99-
void capacity_ArrayBlockingQueue() {
100-
// Arrange
101-
Queue<String> queue = new ArrayBlockingQueue<>(10);
102-
103-
// Act
104-
long queueSize = JcTools.capacity(queue);
105-
106-
// Assert
107-
assertThat(queueSize).isEqualTo(10);
108-
}
10978
}

0 commit comments

Comments
 (0)