JDK-8361382 : NMT corruption: header canary broken as part of CodeBlob::purge()
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 26
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: os_x
  • CPU: x86_64
  • Submitted: 2025-07-03
  • Updated: 2025-08-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 26
26Unresolved
Related Reports
Causes :  
Relates :  
Description
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (mallocHeader.inline.hpp:107), pid=11743, tid=21251
#  fatal error: NMT corruption: Block at 0x000060000133bfd0: header canary broken
#
# JRE version: Java(TM) SE Runtime Environment (26.0) (build 26-internal-2025-07-03-1607476.markus.gronlund.jdkcopy3)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (26-internal-2025-07-03-1607476.markus.gronlund.jdkcopy3, mixed mode, tiered, compressed oops, compressed class ptrs, serial gc, bsd-amd64)
# Core dump will be written. Default location: core.11743

---------------  T H R E A D  ---------------

Current thread (0x00007f8fa3038c10):  VMThread "VM Thread"          [id=21251, stack(0x000070000fb6f000,0x000070000fc6f000) (1024K)]

Stack: [0x000070000fb6f000,0x000070000fc6f000],  sp=0x000070000fc6de50,  free space=1019k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.dylib+0xbf1c8c]  VMError::report(outputStream*, bool)+0xa9c  (mallocHeader.inline.hpp:107)
V  [libjvm.dylib+0xbf5d25]  VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void const*, void const*, char const*, int, unsigned long)+0x575
V  [libjvm.dylib+0x404e20]  DebuggingContext::~DebuggingContext()+0x0
V  [libjvm.dylib+0x8f770f]  MallocHeader* MallocHeader::resolve_checked_impl<void*, MallocHeader*>(void*)+0x15f
V  [libjvm.dylib+0x8f720c]  MallocTracker::record_free_block(void*)+0xc
V  [libjvm.dylib+0x9a719a]  os::free(void*)+0xea
V  [libjvm.dylib+0x388fb4]  CodeBlob::purge()+0x44
V  [libjvm.dylib+0x978e98]  nmethod::purge(bool)+0x308
V  [libjvm.dylib+0x380439]  ClassUnloadingContext::purge_nmethods()+0x69
V  [libjvm.dylib+0xa4d75d]  SerialFullGC::phase1_mark(bool)+0x8ad
V  [libjvm.dylib+0xa4e8d1]  SerialFullGC::invoke_at_safepoint(bool)+0xe1
V  [libjvm.dylib+0xa56a79]  SerialHeap::do_full_collection(bool)+0x369
V  [libjvm.dylib+0xa5b4e0]  VM_SerialGCCollect::doit()+0x30
V  [libjvm.dylib+0xbfc257]  VM_Operation::evaluate()+0xd7
V  [libjvm.dylib+0xc11dcc]  VMThread::evaluate_operation(VM_Operation*)+0xac
V  [libjvm.dylib+0xc125d7]  VMThread::inner_execute(VM_Operation*)+0x297
V  [libjvm.dylib+0xc11add]  VMThread::run()+0xbd
V  [libjvm.dylib+0xb791c8]  Thread::call_run()+0xa8
V  [libjvm.dylib+0x9acccf]  thread_native_entry(Thread*)+0x10f
C  [libsystem_pthread.dylib+0x6202]  _pthread_start+0x63
C  [libsystem_pthread.dylib+0x1bab]  thread_start+0xf
VM_Operation (0x00007000105090a8): SerialGCCollect, mode: safepoint, requested by thread 0x00007f8fa101e210

Comments
[~jsjolen] Yes, I think so. If it was freed it will be set to `blob_end()` address which is inside CodeCache address space: CodeHeap 'non-profiled nmethods': size=120032Kb used=29796Kb max_used=29796Kb free=90235Kb bounds [0x000000011e7c8000, 0x00000001204e8000, 0x0000000125d00000] On other hand, MacOs seems use (based on hs_err file) high addresses `0x000060000*` for malloc. So `_mutable_data` still points to that space.
01-08-2025

[~kvn], do you mean because 0x000060000133bfd0 cannot be blob_end() it cannot be a double-free, but a stomp?
31-07-2025

[~kvn], isn't RunThese30M a very long running "kitchen sink" type of test? I think that UBSAN might make it take far too long. The best way to solve this is to get a hold of a x64 Mac to look at the corefile, but I also think that's not feasible to do. At least, it's not feasible for me.
30-07-2025

Should we run RunThese30M with UBSAN?
29-07-2025

Here is memory block from log: NMT Block at 0x000060000133bfc0, corruption at: 0x000060000133bfc0: 0x000060000133bf40: 40 bf 51 45 17 69 00 00 f1 00 00 00 00 00 00 00 @.QE.i.......... 0x000060000133bf50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000060000133bf60: 00 00 08 80 00 00 00 00 c8 c4 44 51 f8 7f 00 00 ..........DQ.... 0x000060000133bf70: 00 00 00 00 00 00 00 00 e0 b4 fd 51 f8 7f 00 00 ...........Q.... 0x000060000133bf80: 80 bf 51 45 17 69 00 00 fb 07 00 00 00 00 00 00 ..QE.i.......... 0x000060000133bf90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x000060000133bfa0: 08 00 00 00 00 00 00 00 01 00 b4 00 04 00 9e e9 ................ 0x000060000133bfb0: 00 00 00 00 08 00 00 00 e8 8e 00 00 00 00 00 00 ................ 0x000060000133bfc0: d0 31 9f 4e f8 7f 00 00 05 00 00 00 01 00 00 00 .1.N............ 0x000060000133bfd0: 74 61 64 6d 00 00 00 00 00 00 00 00 00 00 00 00 tadm............ 0x000060000133bfe0: 68 32 9f 4e f8 7f 00 00 06 00 00 00 02 00 00 00 h2.N............ 0x000060000133bff0: 63 73 65 64 00 00 00 00 00 00 00 00 00 00 00 00 csed............ 0x000060000133c000: 06 00 00 00 00 00 00 00 00 00 4b 0d 10 00 9e e9 ..........K..... 0x000060000133c010: 67 72 6f 75 70 00 e8 8e 00 00 00 00 00 00 00 00 group........... 0x000060000133c020: 08 00 00 00 00 00 00 00 00 00 67 0d 04 00 9e e9 ..........g..... 0x000060000133c030: 1f 31 00 00 00 00 00 00 e8 8e 00 00 00 00 00 00 .1..............
29-07-2025

Based on hs_err file info in JDK-8364153, 0x000060000133bfd0 could be valid C heap address. So it is not double free. something stomped over header of this memory block. We had before bugs with such stomp - JDK-8358289 Would be interesting to know what was allocated before this memory block.
29-07-2025

Before crash output has next lines: 2025-07-03T21:32:11,778Z] [708.577s][error][jvmti ] Posting Resource Exhausted event: Requested array size exceeds VM limit [2025-07-03T21:32:11,778Z] [711.725s][info ][gc ] GC(1871) Pause Young (Allocation Failure) 4924M->4387M(5763M) 45.309ms [2025-07-03T21:32:11,778Z] [756.385s][error][jvmti ] Posting Resource Exhausted event: Requested array size exceeds VM limit [2025-07-03T21:32:11,778Z] # [2025-07-03T21:32:11,778Z] # A fatal error has been detected by the Java Runtime Environment: [2025-07-03T21:32:11,778Z] # [2025-07-03T21:32:11,778Z] # Internal Error (mallocHeader.inline.hpp:107), pid=11743, tid=21251 [2025-07-03T21:32:11,778Z] # fatal error: NMT corruption: Block at 0x000060000133bfd0: header canary broken
28-07-2025

Isn't this a x64 machine? Host: "Macmini8,1" x86_64 3200 MHz, 12 cores, 32G, Darwin 23.2.0, macOS 14.2 (23C64)
28-07-2025

Hi, I'd like to make it clear that a NMT header corruption is *not* an indication of a bug in NMT. Header corruption indicates that you have a bug in your code, In JDK-8360048, NMT had a bug in its code, and the header corruption crash helped show us that this occurs. This crash indicates a bug in CodeBlob. A 'header corruption' can indicate an issue such as a double-free. I'm removing the relates-to.
28-07-2025

Isn't this another duplicate of JDK-8360048?
10-07-2025

ILW=HLM=P3
08-07-2025