SPECIFIC ISSUE ENCOUNTERED
Over several field-test sessions of an ARCore app on a single Samsung Galaxy A56 (Android 16) we collected 8 native tombstones, all crashing in libarcore_c.so (identical BuildId
15fc3723f0012d756162123aa00372fd). They are not one crash but three related native memory-safety failure modes:
1) Native-peer destruction during GC reclamation (5 of 8) — SIGBUS / SIGSEGV.
When the Java GC reclaims an ARCore wrapper object, the native *_destroy / *_close runs against a corrupted or already-freed native handle:
com.google.ar.core.Frame.finalize → ArFrame_destroy → SIGBUS, PC jumps to garbage 0x10000005e
com.google.ar.core.HitResult.finalize → ArHitResult_destroy → SIGBUS, PC → 0x100000061
NativeAllocationRegistry$CleanerThunk.run → SIGBUS, PC → 0x10000005e
android.hardware.camera2.impl.CameraMetadataNative.finalize → CameraMetadata_close → SIGSEGV (null) — camera metadata finalized with an invalid handle, in the camera2 path ARCore drives (×2)
The near-identical garbage PCs across the SIGBUS cases (0x10000005e / 0x100000061) point to the same corrupted-function-pointer / freed-object signature.
2) Crash inside ARCore's own worker threads (2 of 8) — SIGSEGV.
Pure libarcore_c.so null / near-null dereferences, no app or finalizer frame:
- thread
ms_depth → SIGSEGV, fault addr 0x168 (member access off a null base)
- thread
MTC_mapping → SIGSEGV (null)
3) Heap corruption detected on free (1 of 8) — SIGABRT.
The allocator aborts during free called from libarcore_c.so on the main thread: "Pointer tag for 0x… was truncated" — a double-free / overflow in ARCore native memory.
All occur during normal ARCore use; none is reachable or fixable from app code (we never call these destroy functions — they run on the GC finalizer/cleaner threads or inside ARCore's own threads). The device
has pointer tagging enabled (PR_TAGGED_ADDR_ENABLE), which appears to turn otherwise-silent memory corruption into hard, reproducible crashes — so this device may be a useful signal for latent native
memory-safety bugs.
VERSIONS USED
- Android Studio:
Panda 4 - 2025.3.4 Patch 1 (build toolchain: AGP 9.x, Kotlin 2.3.10, JDK 21)
- ARCore SDK for Android: integrated via SceneView
io.github.sceneview:arsceneview:4.17.0; bundled libarcore_c.so is 1.54
- Device manufacturer, model, and O/S: Samsung Galaxy A56 (
a56x), Android 16
- Google Play Services for AR (ARCore): ~1.54.x —
libarcore_c.so BuildId 15fc3723f0012d756162123aa00372fd (run the adb command above to confirm the exact versionName)
- Output of
adb shell getprop ro.build.fingerprint:
samsung/a56xnaxx/a56x:16/BP4A.251205.006/A566BXXSACZE2_OJMACZE2:user/release-keys
STEPS TO REPRODUCE THE ISSUE
- Run a continuous ARCore session on a Samsung Galaxy A56 / Android 16 (camera tracking active, depth enabled).
- Exercise the API continuously for several minutes — acquire a
Frame every render frame and perform frequent hit-tests (HitResult) while moving the device (tracking / relocalisation stress) — so many
native-backed wrapper objects become garbage and are reclaimed by the GC.
- A crash occurs sporadically (GC-timing / tracking dependent), in one of the three modes above: most often on the
FinalizerDaemon / cleaner thread (ArFrame_destroy / ArHitResult_destroy /
CameraMetadata_close), occasionally inside ARCore's ms_depth / MTC_mapping threads, occasionally as a free-time SIGABRT.
We do not have a deterministic minimal repro — the crashes are non-deterministic and GC-timing dependent — but they recur reliably on this device over normal multi-minute sessions. Full tombstones (text +
.pb) are available.
WORKAROUNDS (IF ANY)
None effective. These are native signals (SIGSEGV / SIGBUS / SIGABRT) on the GC finalizer/cleaner or on ARCore's own threads, so they cannot be caught from Java. We verified the app never retains or
double-frees these objects; reducing Java-object churn does not stop the GC from eventually finalizing them and hitting the native destroy path. Reducing session length / motion lowers the frequency but does
not eliminate the crashes.
ADDITIONAL COMMENTS
Hypothesis: ARCore 1.54 native code mismanages the lifetime/ownership of native peer objects (ArFrame, ArHitResult, camera2 CameraMetadata), so their native resources are freed/corrupted before or while
the GC finalizer / NativeAllocationRegistry cleaner destroys them (use-after-free / double-free), plus separate null-deref crashes inside the depth (ms_depth) and mapping (MTC_mapping) worker threads.
The free-time SIGABRT (truncated pointer tag) is the same memory-safety class caught at allocation time.
Representative backtraces (one per mode; all same device/OS and the identical libarcore_c.so BuildId above):
Mode 1 — ArFrame_destroy on FinalizerDaemon (SIGBUS, fault 0x10000005e):
#00 pc 000000010000005e <unknown>
#04 pc 00000000010ba3f0 libarcore_c.so (ArFrame_destroy+12)
#05 pc 00000000002b03a0 libart.so (art_quick_generic_jni_trampoline+144)
#10 pc ... com.google.ar.core.Frame.finalize+0
#14 pc ... java.lang.Daemons$FinalizerDaemon.doFinalize+208
Mode 1 (camera2 variant) — CameraMetadata_close on FinalizerDaemon (SIGSEGV, null):
#00 pc 0000000000000000 <unknown>
#01 pc 0000000000228f2c /system/lib64/libandroid_runtime.so (CameraMetadata_close(_JNIEnv*, _jclass*, long)+56)
#03 pc ... android.hardware.camera2.impl.CameraMetadataNative.close+124
#04 pc ... android.hardware.camera2.impl.CameraMetadataNative.finalize+116
#05 pc ... java.lang.Daemons$FinalizerDaemon.doFinalize+208
Mode 2 — ARCore worker thread MTC_mapping (SIGSEGV, null), entirely in libarcore_c.so:
#00 pc 0000000001a07d48 libarcore_c.so (offset 0xda8000)
#01 pc 00000000014886e4 libarcore_c.so (offset 0xda8000)
#02 pc 000000000148f0d8 libarcore_c.so (offset 0xda8000)
Mode 3 — heap corruption on free, main thread (SIGABRT):
Abort message: 'Pointer tag for 0x726f772e5d37345b was truncated, see ...tagged-pointers'
#00 pc 00000000000754c8 libc.so (abort+156)
#01 pc 0000000000059500 libc.so (free+104)
#02 pc 0000000001a69798 libarcore_c.so (offset 0xda8000)
We're happy to attach the full text + .pb tombstones, provide more captures, or run instrumented builds.
Mode_1_AR_Frame.zip
Mode_1_Camera_Metadata.zip
Mode_2.zip
Mode_3.zip
SPECIFIC ISSUE ENCOUNTERED
Over several field-test sessions of an ARCore app on a single Samsung Galaxy A56 (Android 16) we collected 8 native tombstones, all crashing in
libarcore_c.so(identical BuildId15fc3723f0012d756162123aa00372fd). They are not one crash but three related native memory-safety failure modes:1) Native-peer destruction during GC reclamation (5 of 8) — SIGBUS / SIGSEGV.
When the Java GC reclaims an ARCore wrapper object, the native
*_destroy/*_closeruns against a corrupted or already-freed native handle:com.google.ar.core.Frame.finalize→ArFrame_destroy→ SIGBUS, PC jumps to garbage0x10000005ecom.google.ar.core.HitResult.finalize→ArHitResult_destroy→ SIGBUS, PC →0x100000061NativeAllocationRegistry$CleanerThunk.run→ SIGBUS, PC →0x10000005eandroid.hardware.camera2.impl.CameraMetadataNative.finalize→CameraMetadata_close→ SIGSEGV (null) — camera metadata finalized with an invalid handle, in the camera2 path ARCore drives (×2)The near-identical garbage PCs across the SIGBUS cases (
0x10000005e/0x100000061) point to the same corrupted-function-pointer / freed-object signature.2) Crash inside ARCore's own worker threads (2 of 8) — SIGSEGV.
Pure
libarcore_c.sonull / near-null dereferences, no app or finalizer frame:ms_depth→ SIGSEGV, fault addr0x168(member access off a null base)MTC_mapping→ SIGSEGV (null)3) Heap corruption detected on free (1 of 8) — SIGABRT.
The allocator aborts during
freecalled fromlibarcore_c.soon the main thread:"Pointer tag for 0x… was truncated"— a double-free / overflow in ARCore native memory.All occur during normal ARCore use; none is reachable or fixable from app code (we never call these destroy functions — they run on the GC finalizer/cleaner threads or inside ARCore's own threads). The device
has pointer tagging enabled (
PR_TAGGED_ADDR_ENABLE), which appears to turn otherwise-silent memory corruption into hard, reproducible crashes — so this device may be a useful signal for latent nativememory-safety bugs.
VERSIONS USED
Panda 4 - 2025.3.4 Patch 1(build toolchain: AGP 9.x, Kotlin 2.3.10, JDK 21)io.github.sceneview:arsceneview:4.17.0; bundledlibarcore_c.sois 1.54a56x), Android 16libarcore_c.soBuildId15fc3723f0012d756162123aa00372fd(run the adb command above to confirm the exact versionName)adb shell getprop ro.build.fingerprint:samsung/a56xnaxx/a56x:16/BP4A.251205.006/A566BXXSACZE2_OJMACZE2:user/release-keysSTEPS TO REPRODUCE THE ISSUE
Frameevery render frame and perform frequent hit-tests (HitResult) while moving the device (tracking / relocalisation stress) — so manynative-backed wrapper objects become garbage and are reclaimed by the GC.
FinalizerDaemon/ cleaner thread (ArFrame_destroy/ArHitResult_destroy/CameraMetadata_close), occasionally inside ARCore'sms_depth/MTC_mappingthreads, occasionally as afree-timeSIGABRT.We do not have a deterministic minimal repro — the crashes are non-deterministic and GC-timing dependent — but they recur reliably on this device over normal multi-minute sessions. Full tombstones (text +
.pb) are available.WORKAROUNDS (IF ANY)
None effective. These are native signals (SIGSEGV / SIGBUS / SIGABRT) on the GC finalizer/cleaner or on ARCore's own threads, so they cannot be caught from Java. We verified the app never retains or
double-frees these objects; reducing Java-object churn does not stop the GC from eventually finalizing them and hitting the native destroy path. Reducing session length / motion lowers the frequency but does
not eliminate the crashes.
ADDITIONAL COMMENTS
Hypothesis: ARCore 1.54 native code mismanages the lifetime/ownership of native peer objects (
ArFrame,ArHitResult, camera2CameraMetadata), so their native resources are freed/corrupted before or whilethe GC finalizer /
NativeAllocationRegistrycleaner destroys them (use-after-free / double-free), plus separate null-deref crashes inside the depth (ms_depth) and mapping (MTC_mapping) worker threads.The
free-timeSIGABRT(truncated pointer tag) is the same memory-safety class caught at allocation time.Representative backtraces (one per mode; all same device/OS and the identical
libarcore_c.soBuildId above):Mode 1 —
ArFrame_destroyon FinalizerDaemon (SIGBUS, fault 0x10000005e):Mode 1 (camera2 variant) —
CameraMetadata_closeon FinalizerDaemon (SIGSEGV, null):Mode 2 — ARCore worker thread
MTC_mapping(SIGSEGV, null), entirely in libarcore_c.so:Mode 3 — heap corruption on free, main thread (SIGABRT):
We're happy to attach the full text +
.pbtombstones, provide more captures, or run instrumented builds.Mode_1_AR_Frame.zip
Mode_1_Camera_Metadata.zip
Mode_2.zip
Mode_3.zip