Implementing Lambda with Capture support makes Metaspace fills LambdaForms$BMH class

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed May 3 12:34:13 UTC 2017


Thanks for the report and for the test case, Wenlei.

What you observe is an unfortunate consequence of LambdaForm 
customization. It was introduced to speedup invocations of non-constant 
method handles (MH.invoke/invokeExact on a method handle which isn't a 
constant during JIT compilation).

As an example from your use case, in order to optimize for the value of 
bound argument, the JIT compiler has to "see" it during the compilation. 
The only way to achieve it right now is by issuing "specialized" 
bytecode for the particular method handle and that's exactly what 
happens during LambdaForm customization.

The generated class should go away once the method handle it was 
generated for becomes unreachable, but it seems you construct plenty of 
method handles for every query.

As a workaround, you can turn it off by specifying:
   -Djava.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD=-1

But I agree with Remi that it's a sign of a deeper problem in how you 
use method handles. MH.bindTo() always produces a new method handle and 
doesn't look like a good fit for implementing lambda capturing.

Method handles are designed for fast invocation. Some non-trivial amount 
of work happens during method handle instantiation, so it should be 
avoided in hot code. From performance perspective, one-time usage of 
method handles never pays off. You should try to cache and reuse them in 
order to observe speedups.

In particular, reusing the same method handle chain for all rows and 
passing the value (from the table) explicitly should lead to a better 
generated code.

Best regards,
Vladimir Ivanov

On 5/2/17 10:29 PM, Wenlei Xie wrote:
> Hi,
>
> We are implementing Lambda function with capture support in a SQL
> Engine. We currently implement by compiling user-written Lambda
> Expression into a MethodHandle. And use bindTo to captured fields. Thus
> for each row we will have a Bound Method Handle.
>
> However, we found JVM will generate the byte code Bound Method Handle
> once it's invoked more than 128 times. This cause in some cases (when
> the table has large arrays), the Metaspace fills with generated
> LambdaForm$BMH class.
>
> Here is the simple code to reproduce the
> issue: https://github.com/wenleix/BMHTest . It looks we cannot increase
> java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD beyond 128. Any
> suggestions to implement Lambda with Capture Support on JVM?
>
> Thank you !!
>
> Best,
> Wenlei
>
>
>
>
>
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>


More information about the mlvm-dev mailing list