ruby-concurrency/concurrent-ruby · critical · RuntimeException
Could not initialize intrinsics
Error message
Could not initialize intrinsics
What it means
On first use, ConcurrentHashMapV8's static initializer reflects on sun.misc.Unsafe.theUnsafe (with setAccessible) to obtain memory-access intrinsics; if a SecurityManager denies it, it retries inside AccessController.doPrivileged. A PrivilegedActionException there is wrapped in RuntimeException("Could not initialize intrinsics"), class initialization fails, and later uses of the class degrade to NoClassDefFoundError. This file is the JRuby/Java half of the concurrent-ruby gem, so the failure surfaces when the JRuby extension loads under restrictive runtimes.
Source
Thrown at ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java:3858
*
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
} catch (SecurityException se) {
try {
return java.security.AccessController.doPrivileged
(new java.security
.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
java.lang.reflect.Field f = sun.misc
.Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (sun.misc.Unsafe) f.get(null);
}});
} catch (java.security.PrivilegedActionException e) {
throw new RuntimeException("Could not initialize intrinsics",
e.getCause());
}
}
}
}
View on GitHub (pinned to 0b88d5ff75)
Solutions
- Run on a standard JVM that ships sun.misc.Unsafe (HotSpot/OpenJDK/OpenJ9 — the normal JRuby target)
- Grant what the initializer needs in the policy: permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; (plus RuntimePermission "accessDeclaredMembers") for the extension jar's code base
- Remove or relax the SecurityManager if it is not actually required
- Use the bundled no-Unsafe build: the com.concurrent_ruby.ext.jsr166e.nounsafe.* sources avoid sun.misc.Unsafe entirely
- If you maintain a fork, replace getUnsafe() with a VarHandle/atomic-field-updater fallback
Example fix
// before: class init fails under a SecurityManager without reflective access
// -> RuntimeException: Could not initialize intrinsics (ExceptionInInitializerError)
// after: grant the permission in the .policy file
// grant codeBase "file:<path-to-concurrent-ruby-ext>" {
// permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
// permission java.lang.RuntimePermission "accessDeclaredMembers";
// };
// or deploy the nounsafe variant shipped in com.concurrent_ruby.ext.jsr166e.nounsafe Defensive patterns
Strategy: validation
Validate before calling
static boolean unsafeAvailable() {
try {
java.lang.reflect.Field f = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return f.get(null) != null;
} catch (Throwable t) {
return false;
}
}
// if (unsafeAvailable()) use the jsr166e classes; else fall back to
// java.util.concurrent.ConcurrentHashMap or the nounsafe build Try / catch
try {
Object m = Class.forName("com.concurrent_ruby.ext.jsr166e.ConcurrentHashMapV8").newInstance();
} catch (ExceptionInInitializerError e) {
Throwable c = e.getCause();
if (c instanceof RuntimeException
&& "Could not initialize intrinsics".equals(((RuntimeException) c).getMessage())) {
// fall back: platform ConcurrentHashMap or nounsafe build; restart if already loaded
} else {
throw e;
}
} Prevention
- Verify the target JVM is a standard OpenJDK/HotSpot/OpenJ9 with sun.misc.Unsafe before deploying sandboxed
- Add ReflectPermission \"suppressAccessChecks\" to the policy for the extension jar
- Smoke-test the first map construction at startup, not mid-request
- Remember the class is dead after the first failure (NoClassDefFoundError) — restart or switch to the nounsafe build
When it happens
Trigger: First touch of ConcurrentHashMapV8 (map construction, JRuby loading the concurrent-ruby Java extension) when: the SecurityManager policy grants neither ReflectPermission("suppressAccessChecks") nor access to sun.misc.Unsafe.theUnsafe; the JVM's class library lacks sun.misc.Unsafe (Android/Dalvik, minimal runtimes); or an agent blocks setAccessible. The first failure surfaces as ExceptionInInitializerError wrapping this RuntimeException; subsequent touches throw NoClassDefFoundError.
Common situations: JRuby plus concurrent-ruby under a SecurityManager (sandboxed/embedded deployments, corporate policy files); nonstandard JVMs without sun.misc.Unsafe; environments where reflection-blocking agents were added. The gem ships a parallel nounsafe source tree (com.concurrent_ruby.ext.jsr166e.nounsafe) precisely to avoid this.
Related errors
- Could not initialize intrinsics
- Required array size too large
- Required array size too large
- cannot enqueue nil
- NullPointerException
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/a5fbba5c206f4de4.
Report an issue: GitHub.