oracle/graal · error · IllegalArgumentException

Could not unwrap a primitive array constant: {}

Error message

Could not unwrap a primitive array constant: {}

What it means

Thrown by HostVMAccess.clonePrimitiveArray when the constant passed the type guard (it types as a primitive array) but SnippetReflectionProvider.asObject(Object.class, primitiveArray) returns null, so the actual array object cannot be retrieved for cloning. It separates 'wrong kind of constant' (previous error) from 'unwrappable constant'.

Source

Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:308

     */
    @Override
    public JavaConstant createPrimitiveArray(JavaKind kind, int length) {
        if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {
            throw new IllegalArgumentException("Expected a non-void primitive kind, got " + kind);
        }
        Object array = Array.newInstance(kind.toJavaClass(), length);
        return providers.getSnippetReflection().forObject(array);
    }

    @Override
    public JavaConstant clonePrimitiveArray(JavaConstant primitiveArray) {
        ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(primitiveArray);
        if (arrayType == null || !arrayType.isArray() || !arrayType.getComponentType().isPrimitive()) {
            throw new IllegalArgumentException("Expected a primitive array constant, got " + primitiveArray);
        }
        Object source = providers.getSnippetReflection().asObject(Object.class, primitiveArray);
        if (source == null) {
            throw new IllegalArgumentException("Could not unwrap a primitive array constant: " + primitiveArray);
        }
        /*
         * Keep cloning explicit by primitive array kind. This avoids reflective clone access and
         * preserves exact array runtime type through each typed clone() call.
         */
        Object copy = switch (source) {
            case boolean[] array -> array.clone();
            case byte[] array -> array.clone();
            case short[] array -> array.clone();
            case char[] array -> array.clone();
            case int[] array -> array.clone();
            case long[] array -> array.clone();
            case float[] array -> array.clone();
            case double[] array -> array.clone();
            default -> throw new IllegalArgumentException("Expected a primitive array constant, got " + primitiveArray);
        };
        return providers.getSnippetReflection().forObject(copy);
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Re-materialize the array as a host object first (e.g. rebuild it from the constant's elements via asArrayConstant) and clone that
  2. Ensure the constant was created by the same SnippetReflectionProvider instance you are unwrapping with
  3. For embedded/image constants, extract elements and reconstruct instead of relying on asObject

Example fix

// before
JavaConstant copy = hostVM.clonePrimitiveArray(embeddedConstant);  // types OK but asObject -> null -> throws

// after
// rebuild a live array constant in this provider context, then clone
JavaConstant live = hostVM.asArrayConstant(componentType, elementsOf(embeddedConstant));
JavaConstant copy = hostVM.clonePrimitiveArray(live);
Defensive patterns

Strategy: validation

Validate before calling

Object probe = snippetReflection.asObject(Object.class, constant);
if (probe == null) { /* rematerialize via asArrayConstant instead of cloning */ }

Type guard

static boolean isLiveHostObject(JavaConstant c, SnippetReflectionProvider s) { return s.asObject(Object.class, c) != null; }

Try / catch

catch (IllegalArgumentException e) { rebuild the array from elements (asArrayConstant) and clone the result }

Prevention

When it happens

Trigger: Calling clonePrimitiveArray with a constant that is statically typed as a primitive array but is not backed by a live host object — e.g. a synthesized/embedded constant (from Content-level data such as an image-heap constant) that snippet reflection cannot map to an Object.

Common situations: Constants obtained from serialized/deserialized compilation data or a different snippet reflection instance losing the object mapping; hotswap/substitution producing synthetic array constants; unwrapping after the underlying object was garbage or the provider context changed between runs.

Related errors


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