{"record":{"id":"8c615c6d1bc70fb2","repo":"oracle/graal","slug":"could-not-unwrap-an-array-constant","errorCode":null,"errorMessage":"Could not unwrap an array constant: {}","messagePattern":"Could not unwrap an array constant: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java","lineNumber":490,"sourceCode":"\n    private ResolvedJavaType lookupType(String name, ClassLoader loader) {\n        try {\n            Class<?> cls = Class.forName(name, false, loader);\n            return providers.getMetaAccess().lookupJavaType(cls);\n        } catch (ClassNotFoundException e) {\n            return null;\n        }\n    }\n\n    @Override\n    public void copyMemory(JavaConstant src, int srcFrom, int srcTo, byte[] dst, int dstFrom) {\n        ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(src);\n        if (arrayType == null || !arrayType.isArray() || !arrayType.getComponentType().isPrimitive()) {\n            throw new IllegalArgumentException(\"Expected a primitive array constant, got \" + src);\n        }\n        var array = providers.getSnippetReflection().asObject(Object.class, src);\n        if (array == null) {\n            throw new IllegalArgumentException(\"Could not unwrap an array constant: \" + src);\n        }\n        int sourceArrayEnd = Array.getLength(array) * arrayType.getComponentType().getJavaKind().getByteCount();\n        if (srcFrom < 0 || srcTo > sourceArrayEnd || srcTo < srcFrom) {\n            throw new IllegalArgumentException(\n                            \"Invalid input range: \" + srcFrom + \"..\" + srcTo + \" for array of length \" + Array.getLength(array) + \" with kind \" + arrayType.getComponentType().getJavaKind());\n        }\n        int bytesToCopy = srcTo - srcFrom;\n        if (dstFrom < 0 || dstFrom > dst.length - bytesToCopy) {\n            throw new IllegalArgumentException(\"Invalid output range: \" + dstFrom + \"..\" + (dstFrom + bytesToCopy) + \" for array of length \" + dst.length);\n        }\n        var unsafe = Unsafe.getUnsafe();\n        unsafe.copyMemory(array, unsafe.arrayBaseOffset(array.getClass()) + srcFrom, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET + dstFrom, bytesToCopy);\n    }\n\n    /**\n     * Host mode performs the unaligned read with {@link Unsafe} against the unwrapped hosted array\n     * object.\n     */","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java#L472-L508","documentation":"copyMemory requires the source constant to be unwrappable to a live host array via snippetReflection.asObject(Object.class, src). The type check passed (it is a primitive array type), but asObject returned null, meaning the constant is not a materialized host object — e.g. null, a placeholder, or a constant created by a different reflection provider.","triggerScenarios":"Calling copyMemory with a constant that types as int[]/long[] etc. but cannot be materialized: NULL_POINTER, constants from another Graal runtime or guest VM, or synthesized constants with no backing object.","commonSituations":"AOT/image-build constants leaking into host-mode APIs; cross-VMAccess constant reuse; tests with hand-built constants.","solutions":["Pre-check with providers.getSnippetReflection().asObject(Object.class, srcConst) and require non-null before copying","Rebuild the constant from the live array via snippetReflection.forObject on the same runtime","Reject non-materializable constants upstream instead of relying on copyMemory's guard"],"exampleFix":"// before\nvmAccess.copyMemory(srcConst, 0, len, dst, 0);\n\n// after\nObject liveArray = providers.getSnippetReflection().asObject(Object.class, srcConst);\nif (liveArray == null) {\n    throw new IllegalStateException(\"src constant has no live host object\");\n}\nvmAccess.copyMemory(srcConst, 0, len, dst, 0);","handlingStrategy":"validation","validationCode":"if (providers.getSnippetReflection().asObject(Object.class, srcConst) == null) {\n    throw new IllegalStateException(\"copyMemory source not materializable: \" + srcConst);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep constants and the VMAccess on the same runtime lifecycle","Rebuild constants from live arrays after any serialization boundary","Fail fast on non-materializable constants in generic byte-dump utilities"],"tags":["graalvm","vmaccess","copymemory","snippet-reflection","constants"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}