Skip to content

[PROF-15786] Reproduce post-JNI Method invalidation - #787

Closed
r1viollet wants to merge 2 commits into
mainfrom
r1viollet/prof-15786-post-jni-method-reproducer
Closed

r1viollet wants to merge 2 commits into
mainfrom
r1viollet/prof-15786-post-jni-method-reproducer

Conversation

@r1viollet

@r1viollet r1viollet commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?:

Adds a regression test for a raw Method* access after HotspotSupport::resolve() leaves its crash-protected metadata walk.

The test makes the fake JVMTI GetClassMethods callback invalidate the page containing the original Method*. The following vm_method->validatedId() call otherwise aborts in assertion-enabled builds.

A second commit contains a candidate fix: use the existing safe load_at_offset path in VMMethod::id() so the read does not pass through VMStructs::at() and its readability assertion.

Motivation:

PR #743 protects the initial metadata walk, but the <clinit> fallback retains and reads vm_method after JNI/JVMTI work and after crash protection has been removed. This draft provides a concrete reproducer and a narrow candidate fix so the lifetime assumptions and preferred resolution can be reviewed.

Additional Notes:

  • The invalidation is synthetic. Whether class unloading, redefinition, or obsolete-method reclamation can produce the same timing in a live JVM still needs investigation.
  • Without the candidate fix, the test observes SIGABRT from the readability assertion in VMStructs::at().
  • The candidate fix is intentionally limited to the first VMMethod::id() load. This draft does not assume that it is the preferred final design.
  • Related change: Protect HotspotSupport::resolve() with longjmp #743

How to test the change?:

./.claude/commands/build-and-summarize :ddprof-lib:gtestDebug_hotspotMethodId
./.claude/commands/build-and-summarize :ddprof-lib:gtestRelease_hotspotMethodId

Both targeted suites pass on Linux with the reproducer enabled and the candidate fix applied.

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles
    credentials of any kind, I've requested a security review (run the dd:platform-security-review
    skill, or file a request via the PSEC review form).
    bewaire also runs automatically on every PR.
  • This PR doesn't touch any of that.
  • JIRA: PROF-15786

Unsure? Have a question? Request a review!

@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Sep 11, 2026

Copy link
Copy Markdown

Pipelines

⚠️ Warnings

Your PR has failed checks. Please review the issues below and take necessary action before merging.

🚦 4 Pipeline jobs failed

DataDog/java-profiler | gtest-asan-amd64

View more details · View in GitLab

DataDog/java-profiler | gtest-asan-arm64

View more details · View in GitLab

DataDog/java-profiler | gtest-tsan-amd64

View more details · View in GitLab

View all 4 failed jobs.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: a41ebb8 | Docs | View more details | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Scan-Build Report

User:runner@runnervmlun5p
Working Directory:/home/runner/work/java-profiler/java-profiler/ddprof-lib/src/test/make
Command Line:make -j4 all
Clang Version:Ubuntu clang version 18.1.3 (1ubuntu1)
Date:Tue Sep 15 13:53:42 2026

Bug Summary

Bug TypeQuantityDisplay?
All Bugs1
Logic error
Dereference of null pointer1

Reports

Bug Group Bug Type ▾ File Function/Method Line Path Length
Logic errorDereference of null pointerfaultInjection.cppcrashNow242

@dd-octo-sts

dd-octo-sts Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #34977710649 | Commit: f58e589 | Duration: 3h 0m 26s (longest job)

All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - - -
8-ibm - - -
8-j9 - -
8-librca - -
8-orcl - - -
11 - - -
11-j9 - -
11-librca - -
17 - -
17-graal - -
17-j9 - -
17-librca - -
21 - -
21-graal - -
21-librca - - 🚫
25 - -
25-graal - -
25-librca - -

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 31 | Failed: 0 | Cancelled: 1


Updated: 2026-09-15 16:53:48 UTC

@zhengyu123

Copy link
Copy Markdown
Contributor

I am confused - what's the purpose of the test? to verify that without longjmp protection, vm_method->validatedId() call can result in crash?

Current vm_method->validatedId() implementation should not crash, as all memory accesses via SafeAccess, but I intent to change to plain accesses with longjmp protection, then fault-injection should be able to trigger the crash to test longjmp recovery.

@r1viollet

Copy link
Copy Markdown
Contributor Author

I am confused - what's the purpose of the test? to verify that without longjmp protection, vm_method->validatedId() call can result in crash?

Current vm_method->validatedId() implementation should not crash, as all memory accesses via SafeAccess, but I intent to change to plain accesses with longjmp protection, then fault-injection should be able to trigger the crash to test longjmp recovery.

@zhengyu123 yes, precisely.

The aim is to give you test cases for your refactors. There is no fix proposal here.
Enabling the reproducer demonstrates the SIGABRT in VMStructs::at() after JVMTI invalidates the raw Method* page.

@zhengyu123

Copy link
Copy Markdown
Contributor

I am confused - what's the purpose of the test? to verify that without longjmp protection, vm_method->validatedId() call can result in crash?
Current vm_method->validatedId() implementation should not crash, as all memory accesses via SafeAccess, but I intent to change to plain accesses with longjmp protection, then fault-injection should be able to trigger the crash to test longjmp recovery.

@zhengyu123 yes, precisely.

The aim is to give you test cases for your refactors. There is no fix proposal here. Enabling the reproducer demonstrates the SIGABRT in VMStructs::at() after JVMTI invalidates the raw Method* page.

@r1viollet We already inject faults at the callsites (https://github.com/DataDog/java-profiler/blob/main/ddprof-lib/src/main/cpp/hotspot/vmStructs.inline.h#L36 and https://github.com/DataDog/java-profiler/blob/main/ddprof-lib/src/main/cpp/hotspot/vmStructs.inline.h#L42), so that some of the faults should propagate to vm_method->validatedId()

@r1viollet

Copy link
Copy Markdown
Contributor Author

thanks for checking! closing this as the fault injection should already cover this.

@r1viollet r1viollet closed this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants