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'.
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
- Element should be an espresso object constant, got
- Expected a non-void primitive kind, got
- Expected a primitive array constant, 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.
Appendix: 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)