Skip to content

Commit 0426932

Browse files
authored
Proactively avoid Unsafe on Java 23+ (#7691)
1 parent fc86cde commit 0426932

File tree

4 files changed

+12
-87
lines changed

4 files changed

+12
-87
lines changed

sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfigurationTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
2020
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
2121
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
22-
import io.opentelemetry.sdk.trace.internal.JcTools;
2322
import java.io.Closeable;
2423
import java.util.ArrayList;
2524
import java.util.Collections;
2625
import java.util.HashMap;
2726
import java.util.LinkedHashMap;
2827
import java.util.List;
2928
import java.util.Map;
30-
import java.util.Queue;
3129
import java.util.concurrent.ArrayBlockingQueue;
3230
import java.util.concurrent.TimeUnit;
3331
import org.junit.jupiter.api.Test;
@@ -140,7 +138,8 @@ void configureBatchLogRecordProcessor() {
140138
assertThat(worker)
141139
.extracting("queue")
142140
.isInstanceOfSatisfying(
143-
Queue.class, queue -> assertThat(JcTools.capacity(queue)).isEqualTo(2));
141+
ArrayBlockingQueue.class,
142+
queue -> assertThat(queue.remainingCapacity()).isEqualTo(2));
144143
assertThat(worker)
145144
.extracting("logRecordExporter")
146145
.isInstanceOf(SystemOutLogRecordExporter.class);

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

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,10 @@
55

66
package io.opentelemetry.sdk.trace.internal;
77

8-
import java.util.Objects;
98
import java.util.Queue;
10-
import java.util.concurrent.ArrayBlockingQueue;
11-
import java.util.concurrent.atomic.AtomicBoolean;
129
import java.util.function.Consumer;
13-
import java.util.logging.Level;
14-
import java.util.logging.Logger;
1510
import org.jctools.queues.MessagePassingQueue;
16-
import org.jctools.queues.MpscArrayQueue;
11+
import org.jctools.queues.atomic.MpscAtomicArrayQueue;
1712

1813
/**
1914
* Internal accessor of JCTools package for fast queues.
@@ -23,38 +18,19 @@
2318
*/
2419
public final class JcTools {
2520

26-
private static final AtomicBoolean queueCreationWarningLogged = new AtomicBoolean();
27-
private static final Logger logger = Logger.getLogger(JcTools.class.getName());
28-
2921
/**
3022
* Returns a new {@link Queue} appropriate for use with multiple producers and a single consumer.
3123
*/
3224
public static <T> Queue<T> newFixedSizeQueue(int capacity) {
33-
try {
34-
return new MpscArrayQueue<>(capacity);
35-
} catch (java.lang.NoClassDefFoundError | java.lang.ExceptionInInitializerError e) {
36-
if (!queueCreationWarningLogged.getAndSet(true)) {
37-
logger.log(
38-
Level.WARNING,
39-
"Cannot create high-performance queue, reverting to ArrayBlockingQueue ({0})",
40-
Objects.toString(e, "unknown cause"));
41-
}
42-
// Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution,
43-
// or a security manager preventing access to Unsafe is installed.
44-
return new ArrayBlockingQueue<>(capacity);
45-
}
25+
return new MpscAtomicArrayQueue<>(capacity);
4626
}
4727

4828
/**
4929
* Returns the capacity of the {@link Queue}. We cast to the implementation so callers do not need
5030
* to use the shaded classes.
5131
*/
5232
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-
}
33+
return ((MessagePassingQueue<?>) queue).capacity();
5834
}
5935

6036
/**
@@ -65,22 +41,7 @@ public static long capacity(Queue<?> queue) {
6541
*/
6642
@SuppressWarnings("unchecked")
6743
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-
}
73-
}
74-
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;
82-
}
83-
return polledCount;
44+
return ((MessagePassingQueue<T>) queue).drain(consumer::accept, limit);
8445
}
8546

8647
private JcTools() {}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import java.security.AccessController;
1212
import java.security.PrivilegedAction;
1313
import java.util.Queue;
14-
import java.util.concurrent.ArrayBlockingQueue;
14+
import org.jctools.queues.atomic.MpscAtomicArrayQueue;
1515
import org.junit.jupiter.api.Test;
1616
import org.junit.jupiter.api.condition.EnabledOnJre;
1717
import org.junit.jupiter.api.condition.JRE;
@@ -30,7 +30,7 @@ void newFixedSizeQueue_SunMiscProhibited() {
3030
Queue<Object> queue =
3131
AccessController.doPrivileged(
3232
(PrivilegedAction<Queue<Object>>) () -> JcTools.newFixedSizeQueue(10));
33-
assertThat(queue).isInstanceOf(ArrayBlockingQueue.class);
33+
assertThat(queue).isInstanceOf(MpscAtomicArrayQueue.class);
3434
} finally {
3535
System.setSecurityManager(null);
3636
}

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

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,18 @@
99

1010
import java.util.ArrayList;
1111
import java.util.Queue;
12-
import java.util.concurrent.ArrayBlockingQueue;
13-
import org.jctools.queues.MpscArrayQueue;
12+
import org.jctools.queues.MessagePassingQueue;
1413
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;
1914

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

2417
ArrayList<String> batch = new ArrayList<>(10);
2518

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-
4219
@Test
4320
void drain_MessagePassingQueue() {
4421
// Arrange
4522
batch.add("Test3");
46-
Queue<String> queue = new MpscArrayQueue<>(10);
23+
Queue<String> queue = JcTools.newFixedSizeQueue(10);
4724
queue.add("Test1");
4825
queue.add("Test2");
4926

@@ -58,7 +35,7 @@ void drain_MessagePassingQueue() {
5835
@Test
5936
void drain_MaxBatch() {
6037
// Arrange
61-
Queue<String> queue = new MpscArrayQueue<>(10);
38+
Queue<String> queue = JcTools.newFixedSizeQueue(10);
6239
queue.add("Test1");
6340
queue.add("Test2");
6441

@@ -79,7 +56,7 @@ void newFixedSize_MpscQueue() {
7956
Queue<Object> objects = JcTools.newFixedSizeQueue(capacity);
8057

8158
// Assert
82-
assertThat(objects).isInstanceOf(MpscArrayQueue.class);
59+
assertThat(objects).isInstanceOf(MessagePassingQueue.class);
8360
}
8461

8562
@Test
@@ -94,16 +71,4 @@ void capacity_MpscQueue() {
9471
// Assert
9572
assertThat(queueSize).isGreaterThan(capacity);
9673
}
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-
}
10974
}

0 commit comments

Comments
 (0)