Skip to content

SIGSEGV in JIT-compiled code with OpenJDK Zulu 25 on Ampere Neoverse-N1 (Project Zomboid B42) #3864

@samuelcarlin037-ship-it

Description

Summary

Box64 v0.4.3 crashes consistently with SIGSEGV in JIT-compiled code when running OpenJDK Zulu 25 on an Ampere Neoverse-N1 (Oracle Cloud A1.Flex). The crash happens during JVM bootstrap, ~14 seconds after process start, inside dynarec-generated code (PC at 0x30050073, not in libjvm.so).

Workaround: forcing pure interpreted mode (-Xint) avoids the crash but performance is severely degraded (~5% of native), making the application barely usable.

Similar in symptoms to #2850 (Zulu 23 + dbeaver) but the affected code is different: this crash is in Java standard library JIT code (jdk.internal.ref.CleanerImpl$CleanableList field access), not in GTK/glib wrapping.

Environment

Box64 version Box64 arm64 v0.4.3 ce3af2bd7 with Dynarec built on May 12 2026 08:43:28
OS Ubuntu 22.04.5 LTS
Kernel Linux 6.8.0-1050-oracle #51~22.04.1-Ubuntu SMP aarch64
Hardware Oracle Cloud Ampere VM.Standard.A1.Flex (4 OCPU, 24 GB RAM)
CPU Neoverse-N1
Page size 4096 (4K)
JVM OpenJDK Zulu25.30+17-CA (build 25.0.1+8-LTS)
VM mode at crash mixed mode, compressed oops, compressed class ptrs, G1GC, linux-amd64
Software Project Zomboid Dedicated Server B42 (v42.18.0, branch -beta unstable, Steam App ID 380870)

Box64 auto-detected JVM settings

After Box64 detects libjvm.so, it automatically applies these settings:

[BOX64] libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem, hide SSE 4.2
[BOX64] BOX64ENV: Variables overridden:
BOX64_DYNAREC_BIGBLOCK=0
BOX64_DYNAREC_SAFEFLAGS=2
BOX64_DYNAREC_STRONGMEM=1
BOX64_JVM=1
BOX64_SSE42=0

Despite these conservative settings, the crash still occurs.

Crash details

SIGSEGV (0xb) at pc=0x0000000030050073, pid=19605, tid=19702
Problematic frame: C 0x0000000030050073
siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000010

The PC 0x30050073 falls in Box64's dynarec-generated code region (not in libjvm.so).

Crash happens ~14 seconds after process start, during JVM warmup.

Crashing thread context

pool-1-thread-1 (Java worker thread, state _thread_in_Java).

Register state at crash:
RAX=0x0000fb7b84010b00, RBX=...
RCX=0x00000007ff871440 ← jdk.internal.ref.CleanerImpl$CleanableList (oop)
RDX=0x00000000000007e8
...
si_addr: 0x10 (NULL+0x10, suggests field offset deref of null)

The thread was executing JIT-compiled bytecode that tried to dereference offset 0x10 from a jdk.internal.ref.CleanerImpl$CleanableList reference. The list's actual fields at this offset are:

private 'head' 'Ljdk/internal/ref/CleanerImplCleanableListCleanableList
CleanableListNode;' @12 (non-null pointer to a Node)
private 'cache' 'Ljdk/internal/ref/CleanerImplCleanableListCleanableList
CleanableListNode;' @16 null

It looks like the dynarec-generated code computed an incorrect base address before the field load — accessing 0x10 (instead of RCX+0x10) strongly suggests address computation went wrong (RCX or base register zeroed out).

C2 CompilerThread0 was simultaneously compiling sun.nio.fs.UnixPath::initOffsets when the crash occurred.

JVM Arguments

-Djava.awt.headless=true
-Xms16g -Xmx16g
-Dzomboid.steam=1 -Dzomboid.znetlog=1
-Djava.library.path=linux64/:natives/
-Djava.security.egd=file:/dev/urandom
-XX:+UseG1GC
-XX:-OmitStackTraceInFastThrow
-XX:-TieredCompilation
-Dsun.reflect.noInflation=true
-Djdk.reflect.useDirectMethodHandle=false
-XX:CompileCommand=exclude,java/lang/Class,reflectionData
-XX:CompileCommand=exclude,zombie/iso/IsoGridSquare,getObjects
-XX:+AlwaysPreTouch
-XX:+PerfDisableSharedMem
-XX:+DisableExplicitGC
-Xshare:off

The last 4 flags (CompileCommand exclude + -XX:-TieredCompilation + reflect tweaks) were attempted as workarounds based on this Steam discussion where the same Java/PZ combination works on FEX-Emu with these flags. They do not help on Box64.

Configurations tested

Configuration Result
Default JVM (full JIT, ZGC) SIGSEGV early (~10s)
G1GC, no other workarounds SIGSEGV early
-XX:TieredStopAtLevel=1 (C1 only) ClassFormatError: Unknown constant tag
FEX-Emu compatible flags (this report) SIGSEGV at ~14s
-Xint (interpreted only) ✅ Works (stable but very slow)

Attached files

  • box64_extract_head.txt — Box64 initialization + env vars + library wrapping (first 200 lines)
  • box64_extract_tail.txt — Box64 rolling log entries leading to crash + NativeBT + EmulatedBT (last 500 lines)
  • hs_err_pid19605.log — full JVM crash report

Question

Are there additional Box64 env vars beyond the libjvm defaults that might mitigate this Java 25 codegen issue? Or planned improvements to dynarec for Zulu OpenJDK 25's JIT output patterns?

Happy to test patches or run additional diagnostic configurations on this hardware. The setup is straightforward to reproduce and the crash is 100% reliable within ~15s of startup.

box64_extract_head.txt
box64_extract_tail.txt
hs_err_pid19605.log

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions