{"record":{"id":"9c45c4cdd08e4479","repo":"oracle/graal","slug":"multiple-uses-of-register-s-s","errorCode":null,"errorMessage":"Multiple uses of register: %s %s","messagePattern":"Multiple uses of register: (.+?) (.+?)","errorType":"exception","errorClass":"GraalError","httpStatus":null,"severity":"critical","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/Assembler.java","lineNumber":349,"sourceCode":"    }\n\n    public int getReturnAddressSize() {\n        return target.arch.getReturnAddressSize();\n    }\n\n    public int getMachineCodeCallDisplacementOffset() {\n        return target.arch.getMachineCodeCallDisplacementOffset();\n    }\n\n    public boolean inlineObjects() {\n        return target.inlineObjects;\n    }\n\n    public static void guaranteeDifferentRegisters(Register... registers) {\n        for (int i = 0; i < registers.length - 1; ++i) {\n            for (int j = i + 1; j < registers.length; ++j) {\n                if (registers[i].equals(registers[j])) {\n                    throw new GraalError(\"Multiple uses of register: %s %s\", registers[i], Arrays.toString(registers));\n                }\n            }\n        }\n    }\n\n    private CodeSnippetRecord currentCodeSnippet = null;\n    private EconomicMap<Integer, CodeSnippetRecord> recordedCodeSnippets = null;\n\n    /**\n     * Marks the start of a {@link CodeSnippetRecord}. If invoked again without a corresponding call\n     * to {@link #stopRecordingCodeSnippet}, the current {@link CodeSnippetRecord} will be\n     * discarded.\n     *\n     * See also {@link #stopRecordingCodeSnippet} and {@link #replayCodeSnippetAt}\n     */\n    public void startRecordingCodeSnippet(CompilationResultBuilder crb) {\n        // not-yet-finished code snippet will be discarded\n        currentCodeSnippet = new CodeSnippetRecord(position(), crb.getSitesWatermark());","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/Assembler.java#L331-L367","documentation":"JNIUtil.createHSArray(JNIEnv, boolean[]) allocates a boolean array in the host VM via JNI NewBooleanArray. If the JNI call returns null, allocation failed on the host side (host heap exhausted or a pending host exception), and the helper throws OutOfMemoryError so the failure is not silently ignored. The copy step only runs after the non-null check.","triggerScenarios":"Host VM heap exhausted when copying a large boolean[] into it via createHSArray; a pending JNI exception from an earlier call making NewBooleanArray return null; host VM under -Xmx pressure inside Espresso/libgraal setups.","commonSituations":"Large array transfers between the guest (native image) and host JVM; host heap sizing too small relative to workload; error paths where an earlier JNI exception was never cleared.","solutions":["Increase the host VM heap (-Xmx on the host JVM) or transfer data in smaller chunks.","Check for and clear pending JNI exceptions before making allocation calls if preceding JNI operations may have failed.","Catch OutOfMemoryError at the call site, release intermediate host references, and retry with a smaller batch."],"exampleFix":"// before\nJBooleanArray hs = JNIUtil.createHSArray(env, hugeArray); // may OOM the host\n\n// after\nJBooleanArray hs = WordFactory.nullPointer();\nfor (int off = 0; off < hugeArray.length; off += CHUNK) {\n    boolean[] chunk = Arrays.copyOfRange(hugeArray, off, Math.min(off + CHUNK, hugeArray.length));\n    JBooleanArray part = JNIUtil.createHSArray(env, chunk);\n    // ... process/append part, releasing it when done\n}","handlingStrategy":"try-catch","validationCode":"// Bound the transfer size before allocating on the host:\nif (a != null && a.length > MAX_HOST_CHUNK) {\n    a = Arrays.copyOf(a, MAX_HOST_CHUNK); // or stream in chunks\n}","typeGuard":null,"tryCatchPattern":"try {\n    return JNIUtil.createHSArray(jniEnv, a);\n} catch (OutOfMemoryError oom) {\n    // host heap exhausted: free other host refs, reduce batch size, then retry with smaller arrays\n    releaseCachedHostRefs();\n    return JNIUtil.createHSArray(jniEnv, Arrays.copyOf(a, a.length / 2));\n}","preventionTips":["Size the host JVM heap (-Xmx) for the largest array you transfer.","Chunk large array transfers instead of allocating one giant host array.","Clear pending JNI exceptions before allocation calls so failures are attributed correctly."],"tags":["jni","out-of-memory","allocation","host-vm"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}