openjdk/jdk · critical

JVM caught ASAN Error

Error message

JVM caught ASAN Error

What it means

The AddressSanitizer error-report callback installed by the JVM (asan_error_callback in hotspot/share/sanitizers/address.cpp). When a JVM is built with ASAN (--with-asan) and ASAN detects a memory error (use-after-free, buffer overflow, etc.), ASAN invokes this callback: it stores the report, prints 'JVM caught ASAN Error' plus the raw ASAN report to stderr, then calls fatal("ASAN Error") so normal JVM error handling produces an hs-err file and terminates the process.

Source

Thrown at src/hotspot/share/sanitizers/address.cpp:50

#ifndef _WINDOWS
#include <dlfcn.h>
#include <stdio.h>

typedef void (*callback_setter_t) (void (*callback)(const char *));
static callback_setter_t g_callback_setter = nullptr;
static const char* g_report = nullptr;

extern "C" void asan_error_callback(const char* report_text) {
  // Please keep things very short and simple here and use as little
  // as possible of any hotspot infrastructure. However shaky the JVM,
  // we should always at least get the ASAN report on stderr.

  // Note: this is threadsafe since ASAN synchronizes error reports
  g_report = report_text;

  // First, print off the bare error to stderr
  fprintf(stderr, "JVM caught ASAN Error\n");
  fprintf(stderr, "%s\n", report_text);

  // Then, let normal JVM error handling run its due course.
  fatal("ASAN Error");
}

void Asan::initialize() {

  // For documentation of __asan_set_error_report_callback() see asan_interface.h .
  g_callback_setter = (callback_setter_t) dlsym(RTLD_DEFAULT, "__asan_set_error_report_callback");
  if (g_callback_setter == nullptr) {
    log_info(asan)("*** Failed to install JVM callback for ASAN. ASAN errors will not generate hs-err files. ***");
    return;
  }

  g_callback_setter(asan_error_callback);
  log_info(asan)("JVM callback for ASAN errors successfully installed");

View on GitHub (pinned to 88dfb74bbe)

Solutions

  1. Read the full ASAN report printed immediately after this line — it names the error type, the faulting stack, and the allocation/free stacks
  2. Reproduce under gdb/ASAN_OPTIONS=abort_on_error=1:symbolize=1 to get a debuggable stack with line info (build with --with-native-debug-symbols=yes)
  3. Fix the actual out-of-bounds / lifetime bug in the native code the report points to (this message itself is not the bug, only the notification)
  4. If the report points into a third-party JNI library, report to that library; if into the JDK, file a JDK bug with the hs-err file and reproduction
Defensive patterns

Strategy: fallback

Validate before calling

# Run ASAN JVM with tight options so reports are actionable:
export ASAN_OPTIONS=abort_on_error=1:detect_leaks=0:symbolize=1
$JDK_ASAN/bin/java -version   # smoke-test before running real tests

Try / catch

This message precedes fatal("ASAN Error") — it cannot be caught. The 'catch' pattern is post-mortem: preserve the hs-err file and stderr ASAN report, then reproduce under gdb with ASAN_OPTIONS=abort_on_error=1 to break at the faulting access.

Prevention

When it happens

Trigger: Any memory error detected by ASAN in JVM native code during execution of an ASAN-instrumented libjvm: heap-buffer-overflow, use-after-free, stack-overflow, SEGV on wild pointer, container-overflow, etc. The message is the JVM-side wrapper; the real cause is in the ASAN report text printed on the following lines.

Common situations: Running tests against a --with-asan built JDK (used by Oracle/SAP CI and by developers hunting native memory bugs); a native library (JNI agent, instrumented JDK patch) introducing an out-of-bounds access; new HotSpot code under review being validated with ASAN.

Related errors


AI-assisted analysis of openjdk/jdk@88dfb74bbe (2026-08-14). Data as JSON: /api/errors/db4cd2fec6004fa7. Report an issue: GitHub.