quarkusio/quarkus · error · RuntimeException

Failed to acquire handle to Module#implAddOpens. This must b

Error message

Failed to acquire handle to Module#implAddOpens. This must be run with JVM parameter '--add-opens=java.base/java.lang.invoke=ALL-UNNAMED'

What it means

ReflectiveAccessModulesReconfigurer obtains a MethodHandle to the internal Module#implAddOpens method (via java.lang.invoke lookup tricks) so it can open JPMS packages without an agent. If the reflective lookup fails (NoSuchFieldException/NoSuchMethodException/IllegalAccessException/InaccessibleObjectException) it throws this RuntimeException telling you the JVM must be started with --add-opens=java.base/java.lang.invoke=ALL-UNNAMED.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/jvm/ReflectiveAccessModulesReconfigurer.java:80

            lookupField.setAccessible(true);

            MethodHandles.Lookup privilegedLookup = (MethodHandles.Lookup) lookupField.get(null);

            //Signature of the method we want to find
            MethodType methodType = MethodType.methodType(void.class, String.class, Module.class);

            //Use the privileged lookup to find the private method
            handle = privilegedLookup.findVirtual(
                    Module.class, // Class to find the method in
                    "implAddOpens", // Name of the private method
                    methodType // Signature of the method
            );

            logger.debug("Successfully acquired MethodHandle for implAddOpens.");
            return handle;

        } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InaccessibleObjectException e) {
            throw new RuntimeException("Failed to acquire handle to Module#implAddOpens. " +
                    "This must be run with JVM parameter '--add-opens=java.base/java.lang.invoke=ALL-UNNAMED'", e);
        }
    }

    /**
     * Uses the MethodHandle to open a package.
     *
     * @param sourceModule The module to open
     * @param packageName The package to open
     * @param targetModule The module to open to
     */
    private void addOpens(Module sourceModule, String packageName, Module targetModule) {
        try {
            implAddOpensHandle.invokeExact(sourceModule, packageName, targetModule);
            logger.debugf("Successfully opened module %s/%s to %s",
                    sourceModule.getName(), packageName, targetModule.isNamed() ? targetModule.getName() : "UNNAMED");
        } catch (Throwable e) {
            // MethodHandle.invokeExact throws Throwable

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add --add-opens=java.base/java.lang.invoke=ALL-UNNAMED to the JVM running the build: export MAVEN_OPTS="--add-opens=java.base/java.lang.invoke=ALL-UNNAMED"
  2. For Gradle, set org.gradle.jvmargs in gradle.properties to include the same --add-opens flag
  3. For IDE runs/tests, add the flag to the JUnit/test JVM arguments (e.g. quarkus.test.arg-line or surefire argLine)
  4. Use a JDK version officially supported by your Quarkus release, where the flag is not needed or documented

Example fix

// before
./mvnw install
// after
export MAVEN_OPTS="--add-opens=java.base/java.lang.invoke=ALL-UNNAMED"
./mvnw install
Defensive patterns

Strategy: validation

Validate before calling

// Check the required add-opens is present before building
String opts = System.getenv("MAVEN_OPTS") == null ? "" : System.getenv("MAVEN_OPTS");
String jvm = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
if (!(opts + jvm).contains("--add-opens=java.base/java.lang.invoke=ALL-UNNAMED")) {
    throw new IllegalStateException("Add --add-opens=java.base/java.lang.invoke=ALL-UNNAMED to the build JVM");
}

Try / catch

try {
    // run the build
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("implAddOpens")) {
        throw new IllegalStateException("Re-run with: MAVEN_OPTS='--add-opens=java.base/java.lang.invoke=ALL-UNNAMED'", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: The build JVM's module system blocks deep reflection into java.lang.invoke: the hidden lookup for Module.implAddOpens cannot access the field/method, which happens on JDKs without the necessary --add-opens flag (especially JDK 16+ strong encapsulation).

Common situations: Running the build on a newer JDK where --add-opens=java.base/java.lang.invoke=ALL-UNNAMED was not propagated (MAVEN_OPTS, gradle.properties, test JVM args); container images with stripped-down JDKs; IDE-launched builds that drop JVM args.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/8dd92f66d6ec4d90. Report an issue: GitHub.