JDK-8078641 : MethodHandle.asTypeCache can retain classes from unloading
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-04-24
  • Updated: 2021-09-13
  • Resolved: 2021-09-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 18
18 b14Fixed
Related Reports
Relates :  
Description
http://mail.openjdk.java.net/pipermail/mlvm-dev/2015-April/006436.html
Peter Levart wrote:

I think there is a Class(Loader) leak in MethodHandle.asType() implementation. If for example some MH (say mhX) is long lived (because it is a system cached MH) and a client "generates" variants from it by invoking mhX.asType(newType) and the newType contains a type (either return type or parameter type) that is loaded by some child ClassLoader, then such derived MH is retained strongly from mhX via the MethodHandle.asTypeCache field. Until this field is overwriten by some other MH, child ClassLoader can not be GCed.

In case this one-element cache is needed to speed things up, it should be a WeakReference, like the following:

http://cr.openjdk.java.net/~plevart/jdk9-dev/MethodHandle.asTypeCacheLeak/webrev.01/


Comments
Changeset: 21012f2b Author: Vladimir Ivanov <vlivanov@openjdk.org> Date: 2021-09-08 11:27:14 +0000 URL: https://git.openjdk.java.net/jdk/commit/21012f2bbe214955d05f8bc583dcdceb0949b601
08-09-2021

http://mail.openjdk.java.net/pipermail/mlvm-dev/2015-April/006441.html: John Rose wrote: This suggests that the right answer is to keep the 1-element cache as-is, but don't fill it with any mh1=mh0.asType(...) for which mh1.type introduces a class loader not already present in mh0.type. I.e., don't use a weak reference for the 1-element cache, but don't fill it with anything that might require a weak reference. Use a backup cache (if needed) to handle exotic type changes. > So maybe, just for the purpose of inexact invoke(), the caching could be performed just in case when asType transformed method type is of the form (Object, Object, ...)Object. This would also prevent accidental thrashing of the cache when inexact invoke() is intermixed with other asType() invocations. The 1-element cache thrashes for other reasons already, and I think we need a multi-way (multi-MH) backup cache of some sort. The backup cache would have weak references. Having a 1-element front-side cache would cover inefficiencies in the backup cache, which in turn would cover inefficiencies for generating new conversion LFs and/or MHs. One interesting point: If we change the 1-element cache to use a weak reference, the cost of reloading the cache will be higher, since each reload must create a new WeakReference instance. This is a possible reason to hold off on the suggested fix. — John
12-07-2021