diff --git a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java index a293c437aff..328e2a993f9 100644 --- a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java +++ b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java @@ -28,9 +28,28 @@ public static Queue newFixedSizeQueue(int capacity) { } catch (java.lang.NoClassDefFoundError e) { // Happens when modules such as jdk.unsupported are disabled in a custom JRE distribution return new ArrayBlockingQueue<>(capacity); + } catch (java.lang.ExceptionInInitializerError e) { + if (isSunMiscAccessProhibited(e)) { + return new ArrayBlockingQueue<>(capacity); + } else { + throw e; + } } } + private static boolean isSunMiscAccessProhibited(Throwable t) { + String rootCause = rootCause(t).getMessage(); + return rootCause != null && rootCause.contains("accessClassInPackage.sun.misc"); + } + + private static Throwable rootCause(Throwable throwable) { + Throwable c = throwable; + while (c.getCause() != null && c.getCause() != c) { + c = c.getCause(); + } + return c; + } + /** * Returns the capacity of the {@link Queue}. We cast to the implementation so callers do not need * to use the shaded classes. diff --git a/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsTest.java b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsTest.java index edb0168d2ce..138249eb90b 100644 --- a/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsTest.java +++ b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsTest.java @@ -7,10 +7,13 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import org.jctools.queues.MpscArrayQueue; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; @@ -106,4 +109,20 @@ void capacity_ArrayBlockingQueue() { // Assert assertThat(queueSize).isEqualTo(10); } + + @Test + void newFixedSizeQueue_works_with_sunMisc_prohibited() { + Assertions.assertNull(System.getSecurityManager()); + SunMiscProhibitedSecurityManager testingSecurityManager = + new SunMiscProhibitedSecurityManager(); + try { + System.setSecurityManager(testingSecurityManager); + Queue queue = + AccessController.doPrivileged( + (PrivilegedAction>) () -> JcTools.newFixedSizeQueue(10)); + Assertions.assertNotNull(queue); + } finally { + System.setSecurityManager(null); + } + } } diff --git a/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/SunMiscProhibitedSecurityManager.java b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/SunMiscProhibitedSecurityManager.java new file mode 100644 index 00000000000..98cee8f972a --- /dev/null +++ b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/SunMiscProhibitedSecurityManager.java @@ -0,0 +1,111 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.trace.internal; + +import java.io.FileDescriptor; +import java.net.InetAddress; +import java.security.AccessControlException; +import java.security.Permission; + +/** + * A security manager which disallows access to classes in sun.misc Running the tests with a + * standard security manager is too invasive + */ +public class SunMiscProhibitedSecurityManager extends SecurityManager { + + public SunMiscProhibitedSecurityManager() {} + + @Override + protected Class[] getClassContext() { + return super.getClassContext(); + } + + @Override + public void checkPermission(Permission perm) { + if (perm.getName().equals("accessClassInPackage.sun.misc")) { + throw new AccessControlException("access denied " + perm, perm); + } + } + + @Override + public void checkPermission(Permission perm, Object context) {} + + @Override + public void checkCreateClassLoader() {} + + @Override + public void checkAccess(Thread t) {} + + @Override + public void checkAccess(ThreadGroup g) {} + + @Override + public void checkExit(int status) {} + + @Override + public void checkExec(String cmd) {} + + @Override + public void checkLink(String lib) {} + + @Override + public void checkRead(FileDescriptor fd) {} + + @Override + public void checkRead(String file) {} + + @Override + public void checkRead(String file, Object context) {} + + @Override + public void checkWrite(FileDescriptor fd) {} + + @Override + public void checkWrite(String file) {} + + @Override + public void checkDelete(String file) {} + + @Override + public void checkConnect(String host, int port) {} + + @Override + public void checkConnect(String host, int port, Object context) {} + + @Override + public void checkListen(int port) {} + + @Override + public void checkAccept(String host, int port) {} + + @Override + public void checkMulticast(InetAddress maddr) {} + + @Override + public void checkPropertiesAccess() {} + + @Override + public void checkPropertyAccess(String key) {} + + @Override + public void checkPrintJobAccess() {} + + @Override + public void checkPackageAccess(String pkg) { + if (pkg.equals("sun.misc")) { + super.checkPackageAccess(pkg); + } + } + + @Override + public void checkPackageDefinition(String pkg) {} + + @Override + public void checkSetFactory() {} + + @Override + public void checkSecurityAccess(String target) {} +}