<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
{font-family:Helvetica;
panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Aptos;
panose-1:2 11 0 4 2 2 2 2 2 4;}
@font-face
{font-family:"Segoe UI";
panose-1:2 11 5 2 4 2 4 2 2 3;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:12.0pt;
font-family:"Aptos",sans-serif;}
h3
{mso-style-priority:9;
mso-style-link:"Heading 3 Char";
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
font-size:13.5pt;
font-family:"Aptos",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.Heading3Char
{mso-style-name:"Heading 3 Char";
mso-style-priority:9;
mso-style-link:"Heading 3";
font-family:"Aptos",sans-serif;
color:#0F4761;}
span.EmailStyle20
{mso-style-type:personal-reply;
font-family:"Aptos",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt">Thanks a lot, Chen<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">-Zhengyu<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="color:black">From:
</span></b><span style="color:black">Chen Liang <liangchenblue@gmail.com><br>
<b>Date: </b>Friday, May 31, 2024 at 10:19</span><span style="font-family:"Arial",sans-serif;color:black"> </span><span style="color:black">AM<br>
<b>To: </b>Zhengyu Gu <zhengyu.gu@servicenow.com><br>
<b>Cc: </b>core-libs-dev@openjdk.org <core-libs-dev@openjdk.org><br>
<b>Subject: </b>Re: Question on Lambda function<o:p></o:p></span></p>
</div>
<div>
<div>
<h3><strong><span style="font-family:Helvetica;color:black;background:yellow">[External Email]</span></strong><span style="font-family:Helvetica"><o:p></o:p></span></h3>
<p class="MsoNormal"><span style="font-family:Helvetica"><o:p> </o:p></span></p>
<div class="MsoNormal" align="center" style="text-align:center"><span style="font-family:Helvetica">
<hr size="0" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal">Hi Zhengyu,<o:p></o:p></p>
<div>
<p class="MsoNormal">This implementation is actually quite good in terms of performance and cost. One improvement you can have is to replace the `invoke` with `invokeExact` (and remember to call MethodHandle.asType() before passing into your anonymous class).<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Unfortunately, it will be somewhat slow due to lack of constant folding, as this handle is not stored in a static final but just an instance final field (without -XX:+TrustFinalNonStaticFields VM flag;
<a href="https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-final-fields">
https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-final-fields/</a>). Therefore, it will be slower than Java 22 MethodHandleProxies (MHP), which uses hidden classes that are automatically trusted.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Your simple implementation is already better than the existing MethodHandleProxies (at least before 22). MHP uses Proxy, which needs to go through InvocationHandler so it had an extra layer of slowness.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Feel free to ask if you have any questions.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Regards,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">Chen<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal">On Fri, May 31, 2024 at 9:03<span style="font-family:"Arial",sans-serif"> </span>AM Zhengyu Gu <<a href="mailto:zhengyu.gu@servicenow.com">zhengyu.gu@servicenow.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Hi Chen,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Do you see any pros and cons of wrapping a MethodHandle, e.g.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">new Function<D, C>() {</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> @Override</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> public C apply(D t) {</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> try {
</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> return (C) handle.invoke(t);
</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> } catch (Throwable e) {
</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> ....
</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> }
</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> }</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<table class="MsoNormalTable" border="0" cellpadding="0" width="1067" style="width:800.4pt;background:white">
<tbody>
<tr>
<td colspan="3" valign="top" style="padding:0in 7.5pt 0in 16.5pt">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:black">vs using MethodHandleProxies.asInterfaceInstance() ?</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:#1F2328"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:#1F2328">I would really appreciate your insights.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:#1F2328"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:#1F2328">Thanks,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:#1F2328"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="color:#1F2328">-Zhengyu</span><o:p></o:p></p>
</td>
<td width="618" colspan="2" style="width:463.5pt;padding:0in 0in 0in 0in">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="color:black"> </span><o:p></o:p></p>
</td>
</tr>
<tr style="box-sizing:border-box">
<td width="403" nowrap="" valign="top" style="width:4.2in;padding:0in 7.5pt 0in 7.5pt;box-sizing:border-box;min-width:50px">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="font-family:"Segoe UI",sans-serif;color:#1F2328"> </span><o:p></o:p></p>
</td>
<td width="74" nowrap="" colspan="2" valign="top" style="width:55.2pt;padding:0in 7.5pt 0in 7.5pt;box-sizing:border-box;min-width:50px" id="m_6241618721485506969diff-d73f79e01daa1c79ac9593c1c9551b086abfff99a8ffb12ac880e5d021601787R69">
<p class="MsoNormal" align="right" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;text-align:right;line-height:15.0pt">
<span style="font-size:10.0pt;font-family:"Times New Roman",serif;color:black"> </span><o:p></o:p></p>
</td>
<td valign="top" style="padding:0in 7.5pt 0in 16.5pt;box-sizing:border-box;outline:transparent dotted 1px">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="font-size:10.5pt;font-family:"Segoe UI",sans-serif;color:#1F2328"> </span><o:p></o:p></p>
</td>
<td style="padding:0in 0in 0in 0in"></td>
</tr>
<tr style="box-sizing:border-box">
<td width="403" nowrap="" valign="top" style="width:4.2in;padding:0in 7.5pt 0in 7.5pt;box-sizing:border-box;min-width:50px">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="font-size:10.5pt;font-family:"Segoe UI",sans-serif;color:#1F2328"> </span><o:p></o:p></p>
</td>
<td width="74" nowrap="" colspan="2" valign="top" style="width:55.2pt;padding:0in 7.5pt 0in 7.5pt;box-sizing:border-box;min-width:50px" id="m_6241618721485506969diff-d73f79e01daa1c79ac9593c1c9551b086abfff99a8ffb12ac880e5d021601787R70">
<p class="MsoNormal" align="right" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;text-align:right;line-height:15.0pt">
<span style="font-size:10.0pt;font-family:"Times New Roman",serif;color:black"> </span><o:p></o:p></p>
</td>
<td valign="top" style="padding:0in 7.5pt 0in 16.5pt;box-sizing:border-box;outline:transparent dotted 1px">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;line-height:15.0pt">
<span style="font-size:10.5pt;font-family:"Segoe UI",sans-serif;color:#1F2328"> </span><o:p></o:p></p>
</td>
<td style="padding:0in 0in 0in 0in"></td>
</tr>
<tr>
<td width="3" style="width:2.25pt;padding:0in 0in 0in 0in;border-width:initial;box-sizing:border-box;min-width:50px">
</td>
<td width="406" style="width:304.5pt;padding:0in 0in 0in 0in"></td>
<td width="38" style="width:28.5pt;padding:0in 0in 0in 0in"></td>
<td width="38" style="width:28.5pt;padding:0in 0in 0in 0in"></td>
<td width="583" style="width:437.25pt;padding:0in 0in 0in 0in"></td>
</tr>
<tr height="0">
<td width="406" style="border:none"></td>
<td width="262" style="border:none"></td>
<td width="25" style="border:none"></td>
<td width="39" style="border:none"></td>
<td width="335" style="border:none"></td>
</tr>
</tbody>
</table>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<div id="m_6241618721485506969mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="mso-margin-top-alt:auto;margin-bottom:12.0pt"><b><span style="color:black">From:
</span></b><span style="color:black">Zhengyu Gu <<a href="mailto:zhengyu.gu@servicenow.com" target="_blank">zhengyu.gu@servicenow.com</a>><br>
<b>Date: </b>Wednesday, May 29, 2024 at 8:28</span><span style="font-family:"Arial",sans-serif;color:black"> </span><span style="color:black">PM<br>
<b>To: </b>Chen Liang <<a href="mailto:liangchenblue@gmail.com" target="_blank">liangchenblue@gmail.com</a>><br>
<b>Cc: </b><a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject: </b>Re: Question on Lambda function</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Hi Chen,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<div id="m_6241618721485506969mail-editor-reference-message-container">
<div>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">What is your usage pattern of these single-abstract-method implementations? Since it sounds like you are<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">creating a lot of them, are you storing them in collections?<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Yes, we do have such usage patterns, e.g. stores methods as Function in hash table as handlers, etc.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">If you are keeping a lot of them in collection (say, as event handlers), you may try to use `MethodHandleProxies.asInterfaceInstance` as a temporary workaround on JDK 22 and higher
(older version uses Proxy, which has horrible invocation performance).<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Thanks for the suggestion. We are currently at 17, I will investigate the library.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Best,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">-Zhengyu</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">If you are on older versions from 15 to 21, unfortunately you might have to write a hidden class for the same purpose or use an existing library. One library that might be useful
is <a href="https://github.com/LanternPowered/Lmbda" target="_blank">https://github.com/LanternPowered/Lmbda</a> that effectively generates unloadable hidden classes, but its 3.x builds are not maven central so you have to build yourself.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">- Chen<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">On Wed, May 29, 2024 at 3:35<span style="font-family:"Arial",sans-serif"> </span>PM Zhengyu Gu <<a href="mailto:zhengyu.gu@servicenow.com" target="_blank">zhengyu.gu@servicenow.com</a>>
wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Hi Chen,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Thanks for the insights.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">We did refactor our code to avoid using LambdaMetaFactory,metafactory() directly.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">With increasing use of Lambdas, in our applications and libraries, the metaspace impact becomes a concern. If current implementation (not able to
unload unused Lambda classes) here to stay, we must come up with a coding guideline to avoid excessive creation of Lambda classes, any pointers or suggestions would be greatly appreciated.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Best,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">-Zhengyu</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> </span><o:p></o:p></p>
<div id="m_6241618721485506969m_-2455228651006166615mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="mso-margin-top-alt:auto;margin-bottom:12.0pt"><b><span style="color:black">From:
</span></b><span style="color:black">Chen Liang <</span><a href="mailto:liangchenblue@gmail.com" target="_blank">liangchenblue@gmail.com</a><span style="color:black">><br>
<b>Date: </b>Wednesday, May 29, 2024 at 2:43</span><span style="font-family:"Arial",sans-serif;color:black"> </span><span style="color:black">PM<br>
<b>To: </b>Zhengyu Gu <</span><a href="mailto:zhengyu.gu@servicenow.com" target="_blank">zhengyu.gu@servicenow.com</a><span style="color:black">><br>
<b>Cc: </b></span><a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a><span style="color:black"> <</span><a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a><span style="color:black">><br>
<b>Subject: </b>Re: Question on Lambda function</span><o:p></o:p></p>
</div>
<div>
<div>
<h3><strong><span style="font-family:Helvetica;color:black;background:yellow">[External Email]</span></strong><o:p></o:p></h3>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:Helvetica"> </span><o:p></o:p></p>
<div class="MsoNormal" align="center" style="text-align:center"><span style="font-family:Helvetica">
<hr size="0" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Hi Gu,<o:p></o:p></p>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">CallSite is specific to each invokedynamic instruction instead of each InvokeDynamic constant pool entry:
<a href="https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-6.html#jvms-6.5.invokedynamic" target="_blank">
https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-6.html#jvms-6.5.invokedynamic</a><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">And the linking is done by MethodHandleNatives.linkCallSite if you want to follow the Java implementation code.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">For why the lambda in the loop is constant, it's a feature from InnerClassLambdaMetafactory: <a href="https://github.com/openjdk/jdk/blob/c8eea59f508158075382079316cf0990116ff98e/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java#L236" target="_blank">https://github.com/openjdk/jdk/blob/c8eea59f508158075382079316cf0990116ff98e/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java#L236</a><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">When the lambda is non-capturing, the bootstrap method LambdaMetafactory.metafactory will eagerly create a singleton instance and return this singleton in the indy instruction.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Also, your metaspace pressure might be caused by the fact that Lambda classes (not instances) are no longer eagerly unloaded; see <a href="https://github.com/openjdk/jdk/pull/12493" target="_blank">https://github.com/openjdk/jdk/pull/12493</a>
and <a href="https://bugs.openjdk.org/browse/JDK-8302154" target="_blank">https://bugs.openjdk.org/browse/JDK-8302154</a>. You are recommended to create your own facility to create hidden classes in Java 17 instead
of continue to use LambdaMetafactory explicitly in code.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Regards,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Chen Liang<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">On Wed, May 29, 2024 at 12:53<span style="font-family:"Arial",sans-serif"> </span>PM Zhengyu Gu <<a href="mailto:zhengyu.gu@servicenow.com" target="_blank">zhengyu.gu@servicenow.com</a>>
wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<div>
<div id="m_6241618721485506969m_-2455228651006166615m_-5447452561659455976mail-editor-reference-message-container">
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222;background:white">Hello Lambda experts,</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">Since we upgraded JDK from 11 to 17, we’re experiencing metaspace pressure, largely due to Lambda class implementation
changes.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">There’s a scenario (see attached test case), that is especially puzzled me, hopefully, you can share some insights.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">In this test case, there is only one Lambda class is created inside the loop, but each one for the same functions outside
loop.</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">Example output:</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">0: Func = LambdaFunc$$Lambda/0x00001f80000c4a20@4de8b406</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">testMethod() called</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">1: Func = LambdaFunc$$Lambda/0x00001f80000c4a20@4de8b406</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">testMethod() called</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">2: Func = LambdaFunc$$Lambda/0x00001f80000c4a20@4de8b406</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">testMethod() called</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">3: Func = LambdaFunc$$Lambda/0x00001f80000c4a20@4de8b406</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">testMethod() called</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">4: Func = LambdaFunc$$Lambda/0x00001f80000c4a20@4de8b406</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222">testMethod() called</span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-family:"Arial",sans-serif;color:#222222"> </span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">….<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Outside loop1, Func = LambdaFunc$$Lambda/0x00001f80000c4c58@402f32ff<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">testMethod() called<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Outside loop2 Func = LambdaFunc$$Lambda/0x00001f80000d1000@5ae9a829<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">testMethod() called<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Outside loop3 Func = LambdaFunc$$Lambda/0x00001f80000d1238@548b7f67<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">testMethod() called<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">And jcmd also confirmed there were 4 Lambda classes created:<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> 49: CLD 0x000060000134cb50: "app" instance of jdk.internal.loader.ClassLoaders$AppClassLoader<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> Loaded classes:<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> 1: LambdaFunc$$Lambda/0x00001f80000d1238<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> 2: LambdaFunc$$Lambda/0x00001f80000d1000
<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> 3: LambdaFunc$$Lambda/0x00001f80000c4c58<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> 4: LambdaFunc$$Lambda/0x00001f80000c4a20<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> 5: LambdaFunc<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Looking into bytecode, all four call sites have the same invokedynamic bytecode (invokedynamic #7, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; ) and the first
invokedynamic bytecode is inside the loop.<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">But when I ran the program with -XX:+TraceBytecodes, it seems that the first invokedynamic was hoisted and result was used in the subsequence loop.<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Can anyone explain where this magic happens? If the magic can apply to the instances outside the loop, so that only one Lambda class is created?<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Thank you for your time and expertise,<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">-Zhengyu<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</body>
</html>