Skip to content
This repository has been archived by the owner on Apr 24, 2023. It is now read-only.

8298084: Memory leak in Method::build_profiling_method_data #13

Closed
wants to merge 6 commits into from

Conversation

coleenp
Copy link
Contributor

@coleenp coleenp commented Dec 9, 2022

This change fixes the MethodData leak by calling the destructor in both the release_C_heap_structures conditionally and by calling the MethodData destructor in the MetadataFactory::free_metadata method.
Thanks to @jcking for working on the patch and discussion.
Tested with tier1-4.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8298084: Memory leak in Method::build_profiling_method_data

Reviewers

Contributors

  • Justin King <jcking@openjdk.org>

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk20 pull/13/head:pull/13
$ git checkout pull/13

Update a local copy of the PR:
$ git checkout pull/13
$ git pull https://git.openjdk.org/jdk20 pull/13/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 13

View PR using the GUI difftool:
$ git pr show -t 13

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk20/pull/13.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Dec 9, 2022

👋 Welcome back coleenp! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot added the rfr Pull request is ready for review label Dec 9, 2022
@openjdk
Copy link

openjdk bot commented Dec 9, 2022

@coleenp The following label will be automatically applied to this pull request:

  • hotspot

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.org label Dec 9, 2022
@mlbridge
Copy link

mlbridge bot commented Dec 9, 2022

Webrevs

@openjdk
Copy link

openjdk bot commented Dec 9, 2022

@coleenp Unknown command author - for a list of valid commands use /help.

@coleenp
Copy link
Contributor Author

coleenp commented Dec 9, 2022

/help

@openjdk
Copy link

openjdk bot commented Dec 9, 2022

@coleenp Available commands:

  • backport - create a backport
  • cc - add or remove an additional classification label
  • clean - Mark the backport pull request as a clean backport
  • contributor - adds or removes additional contributors for a PR
  • covered - used when employer has signed the OCA
  • csr - require a compatibility and specification request (CSR) for this pull request
  • help - shows this text
  • integrate - performs integration of the changes in the PR
  • issue - edit the list of issues that this PR solves
  • jep - require a JDK Enhancement Proposal (JEP) for this pull request
  • label - add or remove an additional classification label
  • open - Set the pull request state to "open"
  • reviewer - manage additional reviewers for a PR
  • reviewers - set the number of additional required reviewers for this PR
  • signed - used after signing the OCA
  • solves - edit the list of issues that this PR solves
  • sponsor - performs integration of a PR that is authored by a non-committer
  • summary - updates the summary in the commit message
  • test - used to run tests

@coleenp
Copy link
Contributor Author

coleenp commented Dec 9, 2022

/contributor add @jcking

@openjdk
Copy link

openjdk bot commented Dec 9, 2022

@coleenp
Contributor Justin King <jcking@openjdk.org> successfully added.

src/hotspot/share/memory/metadataFactory.hpp Outdated Show resolved Hide resolved
@openjdk
Copy link

openjdk bot commented Dec 12, 2022

@coleenp This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8298084: Memory leak in Method::build_profiling_method_data

Co-authored-by: Justin King <jcking@openjdk.org>
Reviewed-by: kbarrett, eosterlund, dholmes, jcking, thartmann

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 11 new commits pushed to the master branch:

  • d453190: 8296955: Kitchensink.java failed with "double free or corruption (!prev): "
  • 8962c72: 8298488: [macos13] tools/jpackage tests failing with "Exit code: 137" on macOS
  • 0267aa5: 8297288: Example code in Scanner class
  • cf93933: 8298271: java/security/SignedJar/spi-calendar-provider/TestSPISigned.java failing on Windows
  • d624deb: 8298459: Fix msys2 linking and handling out of tree build directory for source zip creation
  • a894649: 8298225: [AIX] Disable PPC64LE continuations on AIX
  • 52fffdd: 8298463: tools/javac/modules/EdgeCases.java fails on Windows after JDK-8297988
  • b7b996c: 8298353: C2 fails with assert(opaq->outcnt() == 1 && opaq->in(1) == limit) failed
  • 05d67f6: 8298340: java/net/httpclient/CancelRequestTest.java fails with AssertionError: Found some subscribers for testPostInterrupt
  • 5a92bee: 8298455: JFR: Add logging to TestClose.java
  • ... and 1 more: https://git.openjdk.org/jdk20/compare/553ba65dc44b601e048c53cd1c48d668de9dcf1e...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Dec 12, 2022
Copy link
Contributor

@fisk fisk 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.

@coleenp
Copy link
Contributor Author

coleenp commented Dec 12, 2022

Thanks Erik and Kim. @TobiHartmann and @jcking, do you want to review?

Copy link
Member

@dholmes-ora dholmes-ora left a comment

Choose a reason for hiding this comment

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

Not sure about some of the incidental changes - see below.

Thanks.

src/hotspot/share/memory/metadataFactory.hpp Outdated Show resolved Hide resolved
Comment on lines +2673 to +2675
if (release_sub_metadata) {
methods_do(method_release_C_heap_structures);
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand this aspect of the change. It seems unrelated to the missing destructor issue and seems to cause a significant change in behaviour as we will no longer call methods_do when called from deallocate_contents with the renamed false argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This boolean prevents us from calling the MethodData destructor twice and releasing MethodData C heap memory twice. InstanceKlass::deallocate_contents calls release_C_heap_structures with it false, and then calls through the Metadata pointer hierarchy to MetadataFactory::free_metadata, which calls the MethodData destructor and MethodData::deallocate_contents which calls MethodData::release_C_heap_structures(). This is the delegation scheme for releasing metadata between InstanceKlass and ConstantPool.

InstanceKlass::release_C_heap_structures() is also called during class unloading and must walk the whole metadata, releasing C heap memory. It's passed true. It doesn't go through deallocate_contents because the metadata is freed together at the same time with the metaspace that contains it.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks Coleen I see now how the code has been shuffled around:

Old code:

InstanceKlass::deallocate_contents
-> release_C_heap_structures(/* release_sub_metadata */ false);
  -> methods_do(method_release_C_heap_structures);
    -> m->release_C_heap_structures
      -> method_data()->~MethodData();
-> deallocate_methods(loader_data, methods());
  -> MetadataFactory::free_metadata(loader_data, method);

New code:

InstanceKlass::deallocate_contents
-> release_C_heap_structures(/* release_sub_metadata */ false);
-> deallocate_methods(loader_data, methods());
  -> MetadataFactory::free_metadata(loader_data, method);
    -> method_data()->~MethodData();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, plus releasing the JVMCI thing that MethodData points to also.

Copy link
Member

@dholmes-ora dholmes-ora left a comment

Choose a reason for hiding this comment

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

Thanks Coleen. A couple of further nits on comments but otherwise this seems okay.

Comment on lines 598 to 600
// Can't release the constant pool here because the constant pool can be
// deallocated separately from the InstanceKlass for default methods and
// redefine classes.
Copy link
Member

Choose a reason for hiding this comment

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

Does this comment make sense when the parameter doesn't actually control release of the CP?

Copy link
Contributor Author

@coleenp coleenp Dec 13, 2022

Choose a reason for hiding this comment

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

The comment means it can't release constant pool CHeap structures. It should be inclusive of MethodData also.

@@ -2665,12 +2665,14 @@ static void method_release_C_heap_structures(Method* m) {
}

// Called also by InstanceKlass::deallocate_contents, with false for release_constant_pool.
Copy link
Member

Choose a reason for hiding this comment

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

Comment needs updating.

Comment on lines +2673 to +2675
if (release_sub_metadata) {
methods_do(method_release_C_heap_structures);
}
Copy link
Member

Choose a reason for hiding this comment

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

Thanks Coleen I see now how the code has been shuffled around:

Old code:

InstanceKlass::deallocate_contents
-> release_C_heap_structures(/* release_sub_metadata */ false);
  -> methods_do(method_release_C_heap_structures);
    -> m->release_C_heap_structures
      -> method_data()->~MethodData();
-> deallocate_methods(loader_data, methods());
  -> MetadataFactory::free_metadata(loader_data, method);

New code:

InstanceKlass::deallocate_contents
-> release_C_heap_structures(/* release_sub_metadata */ false);
-> deallocate_methods(loader_data, methods());
  -> MetadataFactory::free_metadata(loader_data, method);
    -> method_data()->~MethodData();

// Call the destructor. This is currently used for MethodData which has a member
// that needs to be destructed to release resources. Most Metadata derived classes have noop
// destructors and/or cleanup using deallocate_contents.
// T is a potentially const or volatile qualified pointer. Remove any const
Copy link
Contributor

Choose a reason for hiding this comment

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

We'll given the template, T by itself is no longer a pointer so its just potentially const or volatile qualified. But that is pedantic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just want to leave it because you're right but pointer is a readable noun here.

Copy link
Member

@TobiHartmann TobiHartmann 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 to me. Thanks for fixing!

@coleenp
Copy link
Contributor Author

coleenp commented Dec 13, 2022

Thanks for the reviews David, Justin and Tobias.
/integrate

@openjdk
Copy link

openjdk bot commented Dec 13, 2022

Going to push as commit 04b8d0c.
Since your change was applied there have been 11 commits pushed to the master branch:

  • d453190: 8296955: Kitchensink.java failed with "double free or corruption (!prev): "
  • 8962c72: 8298488: [macos13] tools/jpackage tests failing with "Exit code: 137" on macOS
  • 0267aa5: 8297288: Example code in Scanner class
  • cf93933: 8298271: java/security/SignedJar/spi-calendar-provider/TestSPISigned.java failing on Windows
  • d624deb: 8298459: Fix msys2 linking and handling out of tree build directory for source zip creation
  • a894649: 8298225: [AIX] Disable PPC64LE continuations on AIX
  • 52fffdd: 8298463: tools/javac/modules/EdgeCases.java fails on Windows after JDK-8297988
  • b7b996c: 8298353: C2 fails with assert(opaq->outcnt() == 1 && opaq->in(1) == limit) failed
  • 05d67f6: 8298340: java/net/httpclient/CancelRequestTest.java fails with AssertionError: Found some subscribers for testPostInterrupt
  • 5a92bee: 8298455: JFR: Add logging to TestClose.java
  • ... and 1 more: https://git.openjdk.org/jdk20/compare/553ba65dc44b601e048c53cd1c48d668de9dcf1e...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Dec 13, 2022
@openjdk openjdk bot closed this Dec 13, 2022
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Dec 13, 2022
@openjdk
Copy link

openjdk bot commented Dec 13, 2022

@coleenp Pushed as commit 04b8d0c.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@coleenp coleenp deleted the method-data branch December 13, 2022 13:05
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
hotspot hotspot-dev@openjdk.org integrated Pull request has been integrated
6 participants