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..e099432ea3b 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"); + } + + public 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/JcToolsSecurityManagerTest.java b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsSecurityManagerTest.java new file mode 100644 index 00000000000..8517c1504b2 --- /dev/null +++ b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/JcToolsSecurityManagerTest.java @@ -0,0 +1,25 @@ +package io.opentelemetry.sdk.trace.internal; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Queue; + + +public class JcToolsSecurityManagerTest { + + @Test + void newFixedSizeQueue_works_with_sunMisc_prohibited() { + SunMiscProhibitedSecurityManager testingSecurityManager = new SunMiscProhibitedSecurityManager(); + System.setSecurityManager(testingSecurityManager); + try { + Queue queue = AccessController.doPrivileged( + (PrivilegedAction>) () -> JcTools.newFixedSizeQueue(10)); + Assertions.assertNotNull(queue); + } finally { + testingSecurityManager.disable(); + } + } + +} 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..cb5532aa144 --- /dev/null +++ b/sdk/trace-shaded-deps/src/test/java/io/opentelemetry/sdk/trace/internal/SunMiscProhibitedSecurityManager.java @@ -0,0 +1,139 @@ +package io.opentelemetry.sdk.trace.internal; + +import java.io.FileDescriptor; +import java.net.InetAddress; +import java.security.AccessControlException; +import java.security.Permission; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * 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 { + + private final AtomicBoolean enabled = new AtomicBoolean(true); + + public void disable() { + enabled.set(false); + } + + public SunMiscProhibitedSecurityManager() {} + + @Override + protected Class[] getClassContext() { + return super.getClassContext(); + } + + @Override + public void checkPermission(Permission perm) { + if (enabled.get() && 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 (enabled.get() && pkg.equals("sun.misc")) { + super.checkPackageAccess(pkg); + } + } + + @Override + public void checkPackageDefinition(String pkg) { + } + + @Override + public void checkSetFactory() { + } + + @Override + public void checkSecurityAccess(String target) { + } + +}