ClassLoader leak in MethodHandle.asType()
Peter Levart
peter.levart at gmail.com
Fri Apr 24 22:24:27 UTC 2015
On 04/24/2015 11:06 PM, John Rose wrote:
> Good point. Are you seeing a leak in practice?
> The cache is important, especially to inexact MH.invoke.
> — John
Well, yes. I am (re)implementing annotations (proxies) using Remi's
Proxy2 and made it all the way except for the following failing jtreg test:
jdk/test/java/lang/annotation/loaderLeak/Main.java
...which made me find this issue. What I'm doing is the following:
For implementing some annotation @Ann proxy's hashCode() method for
example, I prepare DMHs with the following signature (T)int for Ts being
all primitives, primitive arrays, Object[] and Object. I cache them in a
system class static field referenced HashMap keyed by Class<T>. These
are the functions that take an annotation member value and map it to
it's hashCode. When the value is of some Object (or Object[] in case it
is an array) subtype - for example when the member value is an
annotation of type V, I take the (Object)int DMH and transform it with
.asType(methodType(int.class, V.class)) to get (V)int, which is
necessary to further wrap it with filterArguments where the filter is a
member field getter of type (Ann)V so that I get (Ann)int MHs as a kind
of hashCodeExtractors for all annotation members (I'll present the
details later)...
Now if V is an annotation type that is loaded by a child class loader,
it gets retained by system cached DMH.
But now that I'm writing this, I see a workarround. Instead of
transforming hashCode function (Object)int -> (V)int and applying field
getter (Ann)V as an argument filter, I could transform the field getter
argument filter (Ann)V -> (Ann)Object and apply it directly to the
argument of hashCode function (Object)int.
Anyway. The inexact invoke() always transforms a specific MH to a
generic one (Object, Object, ...)Object, right? So using inexact
invoke() on any MH can't trigger the leak. It's just that if someone
attempts to transform a generic MH to some more concrete one to be able
to "connect" it with further transformations does the danger of the leak
appear. 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.
Regards, Peter
>
> On Apr 24, 2015, at 9:14 AM, Peter Levart <peter.levart at gmail.com
> <mailto:peter.levart at gmail.com>> 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/
>> <http://cr.openjdk.java.net/%7Eplevart/jdk9-dev/MethodHandle.asTypeCacheLeak/webrev.01/>
>>
>
>
>
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20150425/19d2fc89/attachment.html>
More information about the mlvm-dev
mailing list