oracle/graal · error · IllegalArgumentException

Expected a primitive array constant, got {}

Error message

Expected a primitive array constant, got {}

What it means

Thrown by HostVMAccess.clonePrimitiveArray when the argument constant does not denote a primitive array: its resolved type is null, not an array, or has a non-primitive component type. It is the entry guard before the constant is unwrapped and dispatched to a typed clone().

Source

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

    /**
     * Host mode materializes the primitive array with reflection and then wraps it as a
     * {@link JavaConstant} through {@link SnippetReflectionProvider#forObject(Object)}.
     */
    @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();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Check the argument first: the constant must type-resolve to an array with primitive component (see the same condition in the guard)
  2. Use the dedicated array clone paths for object arrays instead of clonePrimitiveArray
  3. Ensure the constant was produced by forObject over a real primitive array (int[], double[], ...) in the same provider context

Example fix

// before
JavaConstant copy = hostVM.clonePrimitiveArray(objectArrayConstant);  // throws

// after
ResolvedJavaType t = metaAccess.lookupJavaType(constant);
if (t != null && t.isArray() && t.getComponentType().isPrimitive()) {
    JavaConstant copy = hostVM.clonePrimitiveArray(constant);
}
Defensive patterns

Strategy: type-guard

Validate before calling

ResolvedJavaType t = metaAccess.lookupJavaType(constant);
boolean ok = t != null && t.isArray() && t.getComponentType().isPrimitive();

Type guard

static boolean isPrimitiveArrayConstant(JavaConstant c, MetaAccessProvider m) {
    ResolvedJavaType t = m.lookupJavaType(c);
    return t != null && t.isArray() && t.getComponentType().isPrimitive();
}

Try / catch

catch (IllegalArgumentException e) { route object arrays to their own clone path }

Prevention

When it happens

Trigger: Calling clonePrimitiveArray(constant) where metaAccess.lookupJavaType(primitiveArray) is null or the type fails isArray()/getComponentType().isPrimitive() — e.g. passing an Object[] constant, a boxed scalar constant, or a constant the meta access cannot type.

Common situations: Generic deep-copy helpers applied to any constant without checking the component kind; refactors where a primitive array is replaced by a boxed/wrapper array; constants coming from a different meta-access context that cannot be typed.

Related errors


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