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.lev...@gmail.com <mailto:peter.lev...@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@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to