Skip to content

Potential memory leak with the JVMTI wallclock sampler #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

zhengyu123
Copy link
Contributor

@zhengyu123 zhengyu123 commented Jun 30, 2025

What does this PR do?:
Release jthread local reference to prevent memory leak.

Profiler uses jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr) to obtain a list of running threads. The document states

On return, the jthread* points to a newly allocated array of size *threads_count_ptr. The array should be freed with [Deallocate](https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#Deallocate). The objects returned by threads_ptr are JNI local references and must be [managed](https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#refs).

The returned array contains JNI local references of threads, should be managed by caller, which means the caller should manage the life cycle of returned JNI local reference. In this case, we should delete those JNI local references to avoid the leak.

Motivation:
Make JVMTI wallclock sampler useable.

Additional Notes:

How to test the change?:
Run:

java -javaagent:/Users/zhengyu.gu/ws/dd-java-agent.jar -Ddd.profiling.enabled=true -Ddd.profiling.upload.period=10 -Ddd.profiling.start-force-first=true -Ddd.profiling.ddprof.debug.lib=/Users/zhengyu.gu/go/src/github.com/DataDog/java-profiler/ddprof-lib/build/lib/main/debug/macos/arm64/libjavaProfiler.dylib -Ddd.env=workspace-jb -Ddd.service=akka-uct -XX:NativeMemoryTracking=summary -Ddd.profiling.smap.aggregation.enabled=false -Ddd.profiling.experimental.ddprof.wall.jvmti=true -Ddd.profiling.ddprof.wall.context.filter=false -jar renaissance-gpl-0.16.0.jar akka-uct -r 500000

It crashes without this fix, no crash with the fix.

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 review from @DataDog/security-design-and-guidance.
  • This PR doesn't touch any of that.
  • JIRA: PROF-10859

Unsure? Have a question? Request a review!

Copy link

github-actions bot commented Jun 30, 2025

🔧 Report generated by pr-comment-cppcheck

CppCheck Report

Errors (2)

Warnings (4)

Style Violations (301)

Copy link

github-actions bot commented Jun 30, 2025

🔧 Report generated by pr-comment-scanbuild

@zhengyu123 zhengyu123 marked this pull request as ready for review June 30, 2025 19:51
@zhengyu123 zhengyu123 marked this pull request as draft June 30, 2025 20:07
Copy link
Collaborator

@jbachorik jbachorik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@@ -165,6 +165,7 @@ class WallClockJVMTI : public BaseWallClock {
struct ThreadEntry {
ddprof::VMThread* native;
jthread java;
int tid;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit - maybe premature optimization but can we 'unionize' the native and tid since they will never be used at the same time?

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