LambdaMetafactory requires full privilege access, but doesn't seem to actually restrict functionality

Michael Kuhlmann jdk at fiolino.de
Thu Jan 20 20:37:16 UTC 2022


Hi Steven!

On 1/19/22 2:23 AM, Steven Schlansker wrote:
> Interestingly, that wasn't what I found.  At least as of Java 14, the Metafactory generation approach (as limited as my first pass was) was competitive with CGLib hand-generated code in many (but not all) cases, and significantly faster than Method.invoke:
> https://github.com/FasterXML/jackson-modules-base/tree/2.14/blackbird/benchmarks
> Unfortunately I don't have a MethodHandle.invokeExact comparison in that benchmark. I should go back and finish that work, and re-run it all on 17. If we can call non-static MethodHandles with little overhead, then any reason to use the Metafactory here goes away.

Very interesting! Thank you for sharing it.
It's true that for non-static MethodHandles it's a similar problem as 
for generic lambdas: Hotspot can't easily inline the call. I wouldn't 
have expected that MethodHandles are even slower than lambas, but 
honestly I never measured it.

> 
>> Really, I'm curious if this could be an approach for Jackson. Or if not, what could be the obstacles.
> 
> I think the problem here is just slightly different: your approach will copy from one Java object to another Java object, but what we are doing is reacting to a token stream and trying to bind it to Java objects with as little overhead as possible.

So I assume your token handler is getting the caller (be it a handle, a 
lambda or whatever) from some key-value store (maybe a Map) and 
injecting the value into it.

What you can try is using MethodHandles::exactInvoker combined with 
foldArguments, where the token-to-handle mapper is already injected. 
The handle would just expect the token key and the value as arguments. 
Maybe this would perform better then the non-static setter handles.

I did this for another use case where the target handle was the 
dynamicInvoker of a MutableCallSite. The handle then lazily generated 
its own final handle on the first call and set it into its CallSite, so 
that all subsequent calls ran directly into the generated handle. It was 
working great and a lot of fun to code, but again, I never measured the 
performance in detail.

I wish you good luck!
Michael


More information about the core-libs-dev mailing list