RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v12]

Rémi Forax forax at openjdk.org
Tue May 2 21:28:24 UTC 2023


On Tue, 2 May 2023 21:22:16 GMT, Chen Liang <liach at openjdk.org> wrote:

>> As John Rose has pointed out in this issue, the current j.l.r.Proxy based implementation of MethodHandleProxies.asInterface has a few issues:
>> 1. Exposes too much information via Proxy supertype (and WrapperInstance interface)
>> 2. Does not allow future expansion to support SAM[^1] abstract classes
>> 3. Slow (in fact, very slow)
>> 
>> This patch addresses all 3 problems:
>> 1. It implements proxies with one hidden class for each requested interface and replaced WrapperInstance inheritance with a check to the class data. This can avoid unexpected passing of `instanceof`, and avoids the nasty problem of exporting a JDK interface to a dynamic module to ensure access.
>> 2. This patch obtains already generated classes from a ClassValue by the requested interface type; the ClassValue can later be updated to compute implementation generation for abstract classes as well.
>> 3. This patch's generated hidden classes has call performance on par with those of lambda expressions; the creation performance is slightly less than that of LambdaMetafactory: https://jmh.morethan.io/?gist=fcb946d83ee4ac7386901795ca49b224
>> 
>> Additionally, an obsolete `ProxyForMethodHandle` test was removed, for it's no longer applicable. Tests in `jdk/java/lang/invoke` and `jdk/java/lang/reflect` pass.
>> 
>> [^1]: single abstract method
>
> Chen Liang has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Minor cleanup, attempt to migrate lookup validation blocked by security manager

I disagree for two reasons
- the first is inlining, 2ns/op vs 6ns/op is not very relevant, what is relevant is that in case you have full inlining of the callee inside the caller code and not in the other case. As Cliff Click said, inlining is the mother of all optimizations, without inlining there is a bunch of other optimizations that can not be applied. Moreover, in a lot of cases where proxies are used (Spring, CDI, Logger, etc), proxies are composed, if each call through a proxy is not inlined the performance difference is massive.
- second is control, as a user i've the control on the profile pollution that occurs because of the use of the proxy interface while i've no control on the profile pollution dues to the proxy implementation which depend on how others parts / libraries of the application are also using proxies.

And I don't buy the Leyden argument, the condensers of Leyden act at jlink time. A condenser is free to use a different strategy or not that the one used at runtime. Currently, GraalVM AOT, the closest existing thing to Leyden is using two entrypoints, one for the classical JDK and one for Graal AOT. Why not using the two entrypoints strategy for MHProxies.asInterfaceInstance() when Leyden will be implemented ?

-------------

PR Comment: https://git.openjdk.org/jdk/pull/13197#issuecomment-1532173983


More information about the core-libs-dev mailing list