JDK-8268088: Clarify Method::clear_jmethod_ids() related comments in ClassLoaderData::~ClassLoaderData() #4383
Some more background context related to this:
Users/developers would be happy if we can release memory for jmethod_ids in unloaded cases and get rid of the memory leak. I was pinged recently for the leak after the earlier unsuccessful attempt to fix with 66ef04a change (on JDK 11, and was rollback due to agent crashes). I haven't found a general solution that would work well without the memory leak. So decided to clarify the comment for now and also open up the discussion in JDK-8268088.
The agent that ran into crashes with the attempted fix saved stacktraces and jmethod_ids from periodic sampling. It then tried to get the class and method information (name, etc) from the saved jmethod_ids at later points during the execution and crashed in Method::checked_resolve_jmethod_id with a stale jmethod_id. One possible solution that I thought of was to 'remove' the jmethod_ids in agent during unloading (described in https://bugs.openjdk.java.net/browse/JDK-8268088?focusedCommentId=14424635&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14424635). That could allow deallocating the memory related to those jmethod_ids within the VM. However, that's not a general and efficient solution because:
It would be good if we can find a workable solution for this (for long term).
Hi, I put a short comment in JDK-8268088 which I'll expand later. There's already a JVMTI callback for unloading classes that the user could use to walk the saved jmethodID stacks:
// notify the debugger
Otherwise, don't change class unloading to add a callback because it could be sensitive to safepoints and unsafe places.
My comment in this bug echoes what Ioi said above. To prevent class unloading, the class mirror should be saved with the Method. This is the approach taken throughout the vm. I think hunting down applications that need to fix their profilers may be difficult, but we could add some deprecation messages and warnings (or even an option, which I thought was what you were going to do). I'm not sure why so many lines are changed in your above pull request.
For now the updated message seems fine to me for JDK 17.
@jianglizhou This change now passes all automated pre-integration checks.
After integration, the commit message for the final commit will be:
At the time when this comment was updated there had been 67 new commits pushed to the
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.
A new capability as Ioi suggested in https://bugs.openjdk.java.net/browse/JDK-8268364?focusedCommentId=14426310&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-14426310 would be better than using the existing callback for unloading. The possible approach that I described in https://bugs.openjdk.java.net/browse/JDK-8268088?focusedCommentId=14424635&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-14424635 also looks for the same direction (however there are still other issues as described in the bug comment). Also, we need a good strategy for existing code that expects the current behavior.
Prevent or defer class unloading would keep more memory for longer time. It could cause other unwanted side-effects.
Do you refer to 66ef04a? That's based on my internal change on JDK 11 (with other local changes). I restructured code by moving JNIMethodBlock and JNIMethodBlockNodes class declarations to the header file. That's needed to trigger destructor properly from classLoaderData.cpp. The original logic was kept the same, and only the code was being moved around.
I opened my internal change for reference purposes and assisting the discussions to address the memory leak.
@jianglizhou Since your change was applied there have been 73 commits pushed to the
Your commit was automatically rebased without conflicts.
Pushed as commit ae16052.