JDK-8268088 : Clarify Method::clear_jmethod_ids() related comments in ClassLoaderData::~ClassLoaderData()
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 11,17
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2021-06-02
  • Updated: 2021-06-11
  • Resolved: 2021-06-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17
17 b26Fixed
Related Reports
Relates :  
Relates :  
Description
Our developers noticed a memory leak with Method::ensure_jmethod_ids for a longer running application. The allocated JNIMethodBlockNodes are not freed after the associated user defined class loaders are unloaded. The daily leak is ~20MiB - ~70MiB. Please see the initial discussion in https://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2021-January/044946.html. The following comments in 
https://github.com/openjdk/jdk/blob/379376f0783facba93e1d11db9b184ef8183a13b/src/hotspot/share/classfile/classLoaderData.cpp#L697 indicate the leak is intentional:

  // Clear all the JNI handles for methods
  // These aren't deallocated and are going to look like a leak, but that's
  // needed because we can't really get rid of jmethodIDs because we don't
  // know when native code is going to stop using them.  The spec says that
  // they're "invalid" but existing programs likely rely on their being
  // NULL after class unloading.

Our attempted fix (https://github.com/openjdk/jdk/commit/66ef04af110862a1a6b727f12ad5eed9c26cd5a9) ran into SEGV crash in production environment when a profiler agent was enabled. The agent  captured stack traces and then symbolized methods using jmethod_ids at a later point during runtime execution, which could happen after unloading the associated classes and loaders. 

Further investigations have not yet found a more suitable approach than the existing one in Hotspot, which sets jmethod_ids to NULL instead of freeing the related memory during unloading. The existing approach mostly like was selected when considering the trade-off among stability, complexity and memory usage (although no additional background information has been located).

This bug is created to further clarify the comments in ClassLoaderData::~ClassLoaderData() for Method::clear_jmethod_ids() to explain why it is unsafe to release jmethod_id memory.
Comments
Changeset: ae160529 Author: Jiangli Zhou <jiangli@openjdk.org> Date: 2021-06-08 20:35:40 +0000 URL: https://git.openjdk.java.net/jdk/commit/ae16052951fbff21abf02271b761055cd2eed14b
08-06-2021

The way to keep Methods alive is to store the mirror jobject for the owning class with that Method, to prevent unloading.
08-06-2021

One possible approach that we discussed was to 'remove' the jmethod_ids in profiler agent during unloading. That could allow deallocating the memory related to those jmethod_ids within the VM. However, that's not a general/good solution because: - It requires a new call back being registered and implemented from the agent. An agent may not choose to do so. - It adds overhead to class unloading. The agent would need to iterate all stored stack traces and find the jmethod_ids related to the classes that are currently being unloaded. That can be expansive and would add noticeable overhead. Also, agent may have bugs and fail to remove a jmethod_ids during the callback. JVM cannot reliably free the memory without a potential SEGV risk with the approach. Would love to hear and discuss other possible approaches that could address the memory leak.
02-06-2021