oracle/graal · error · IllegalArgumentException

JImage=native can only be set if native access is allowed

Error message

JImage=native can only be set if native access is allowed

What it means

EspressoEnv validates at startup that the option espresso.JImage=native is only used when native access is allowed (AllowNativeAccess / the NativeAccessAllowed gate). A native jimage reader uses native code to memory-map the runtime's modules image; without native access permission that path cannot be taken, so the constructor throws IllegalArgumentException immediately instead of failing later.

Source

Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoEnv.java:176

                multiThreadingDisabledReason = "context seems to contain single-threaded languages: " + singleThreadedLanguages;
                context.getLogger().warning(() -> "Disabling multi-threading since the context seems to contain single-threaded languages: " + singleThreadedLanguages);
            }
        }
        this.multiThreadingDisabled = multiThreadingDisabledReason;
        this.NativeAccessAllowed = env.isNativeAccessAllowed();
        this.Polyglot = env.getOptions().get(EspressoOptions.Polyglot);
        this.HotSwapAPI = env.getOptions().get(EspressoOptions.HotSwapAPI);
        this.BuiltInPolyglotCollections = env.getOptions().get(EspressoOptions.BuiltInPolyglotCollections);
        this.polyglotTypeMappings = new PolyglotTypeMappings(env.getOptions().get(EspressoOptions.PolyglotInterfaceMappings), env.getOptions().get(EspressoOptions.PolyglotTypeConverters),
                        BuiltInPolyglotCollections);
        this.enableGenericTypeHints = env.getOptions().get(EspressoOptions.EnableGenericTypeHints);
        this.proxyCache = polyglotTypeMappings.hasMappings() ? new HashMap<>() : null;
        this.UseBindingsLoader = env.getOptions().get(EspressoOptions.UseBindingsLoader);
        this.AdvancedRedefinition = env.getOptions().get(EspressoOptions.EnableAdvancedRedefinition);

        EspressoOptions.JImageMode requestedJImageMode = env.getOptions().get(EspressoOptions.JImage);
        if (!NativeAccessAllowed && requestedJImageMode == EspressoOptions.JImageMode.NATIVE) {
            throw new IllegalArgumentException("JImage=native can only be set if native access is allowed");
        }
        this.JImageMode = requestedJImageMode;

        this.vmArguments = buildVmArguments(context.getLogger());
        this.jdwpContext = new JDWPContextImpl(context);
        if (env.getOptions().get(EspressoOptions.CHA)) {
            this.classHierarchyOracle = new DefaultClassHierarchyOracle();
        } else {
            this.classHierarchyOracle = new NoOpClassHierarchyOracle();
        }
    }

    public TruffleLanguage.Env env() {
        return env;
    }

    public boolean multiThreadingEnabled() {
        return multiThreadingDisabled == null;

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Remove espresso.JImage=native and let Espresso use the pure-Java image reader (default).
  2. If native image reading is required, enable native access: Context.newBuilder().allowNativeAccess(true) (or remove the NativeAccess restriction) and keep the option.
  3. Check for stale option files (e.g. .polyglotrc, system properties, launcher flags) that still set JImage=native.

Example fix

// before
Context ctx = Context.newBuilder("java").allowNativeAccess(false).option("espresso.JImage", "native").build(); // throws

// after
Context ctx = Context.newBuilder("java").allowNativeAccess(false).build(); // java reader, no option
Defensive patterns

Strategy: validation

Validate before calling

// Validate option combination before building the Context
boolean nativeAllowed = builder.getAllowedNativeAccess(...) /* or your config */;
if (!nativeAllowed) {
    // do not set espresso.JImage=native
}

Try / catch

try {
    Context.newBuilder("java").option("espresso.JImage", "native").build();
} catch (IllegalArgumentException e) {
    // fall back to building without the JImage option
}

Prevention

When it happens

Trigger: Starting a polyglot Context with option espresso.JImage=native while the embedding does not grant native access (e.g. a native-image host compiled with --no-fallback semantics, or a Context configured without allowNativeAccess(true) and polyglot engine restriction 'NativeAccess' false).

Common situations: Sandboxed or restricted polyglot hosts (allowNativeAccess(false)) that still pass JImage=native for speed; upgrading GraalVM where the option became gated; CI sandboxes that deny native access by default.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/fa66f55dfc217426. Report an issue: GitHub.