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
- Re-materialize the array as a host object first (e.g. rebuild it from the constant's elements via asArrayConstant) and clone that
- Ensure the constant was created by the same SnippetReflectionProvider instance you are unwrapping with
- 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
- Use one SnippetReflectionProvider instance for create and unwrap
- Rematerialize embedded/deserialized constants before host operations
- Treat unwrappable constants as data, not live objects
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
- Could not obtain the original class for {}
- Expected a non-void primitive kind, got {}
- Expected a primitive array constant, got {}
- Expected an array constant for src, got {}
- Expected an array constant for dest, got {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/5bf3459d98884416.
Report an issue: GitHub.