-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Replace Reflection usage with MethodHandle
(3.0)
#2083
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@hc-codersatlas Do you think As to versioning... this is bit tricky, since although Jackson 2.7 and above do require Java 7 to compile, we do not currently require anything beyond Java 6 for running Jackson 2.x. So perhaps this could be done for 2.10, if there are indications there are benefits; either regarding performance or forwards-compatibility with Java 9. |
One note on SO answer: I think the reason I saw no benefit was since Jackson actually forcibly disables access checks, so no dynamic checks are made. So the main benefit (if so) would be that no calls would be needed except to work around access limitations (which will also be problematic no matter what, I think, on Java 9). |
MethodHandle is more efficient. It's the engine behind lambda and other invokedynamic uses. Hotspot / Java optimized MethodHandle rigorously from Java 8 onwards 9as per SO post). Anything MethodHandle / Varhandle / AtomicFieldUpdater etc gets trusted by Hotspot to do constant folding (as of 8/9). Under the hood a lot of it just compiles down to Unsafe calls without using Unsafe (or intrinsics). Lambda came out in 8 so if you tested in using 7 that might be the difference. It's the long term option in terms of moving forward too - reflection is a broken mess from 9 onwards. |
@cowtowncoder My English is not good, so I just translate above with machine. Under the default configuration of |
This is the test code.
output with jvm param
|
At this point anyone who wants to propose changes to use Alternatively this could also work as part of Afterburner module, initially; I think there are plans by @stevenschlansker to prototype it. |
Switching from classic Reflection to The potential benefit, as @IrvingZhao highlights above, is avoiding costs of inflating The drawback is that accessing private fields and methods in the same was as It would be very interesting to prototype this change and then compare performance. My personal prediction is that we find on modern JVMs it hardly matters at all: vanilla classic reflection vs vanilla MethodHandle vs Afterburner vs Blackbird, none of them delivers noticesable performance increases in the context of even a single database call or WAN HTTP request. But I still think the work is worth doing to use more modern approaches with possible future benefits to |
Makes sense. So, on 3.0: I am focusing now on 2.10, to get it out the door. After that I could go back to 3.0 development -- so far most work has been with scaffolding, API changes (builder pattern), removing deprecated things, making things immutable. It may even be possible/desireable to move past Java 8 as baseline (if so, 11 being LTR), but that's different discussion to have. |
As of Java 18, there no longer is a historical Reflection api implementation at all, it simply becomes calls into MethodHandles, but slightly less efficient. So we definitely should migrate: |
Oh fuck. |
ASM is now bundled/released just before JRE and is bundled with the JDK now though - ? My understanding is that it is better to avoid reflection and proxy class into your encapsulated module-space so consuming libraries dont need to |
I suppose I am not quite clear on what Reflection api implementation here specifically means. It sounds like some aspects might be removed? I wouldn't think all basic Quick glance at linked-to article seems to suggest this is implementation change, not API. |
Nothing will be removed at the API level. The reflection API's backing implementation will be replaced. It might be slower but won't break. |
I'm hacking around on this here: https://github.com/FasterXML/jackson-databind/compare/master...stevenschlansker:methodhandle-hacking?expand=1 39 failing tests to go... |
Adding a comment here, as noted in the mentioned JEP there won't be any performance advantage (apart from saving inflation, which is still a concern!) If the Field/Methods are saved (and called by) into non static final fields. Quoting the relevant part of the JEP, FYI
Currently the only unsafe but faster way to perform field's get without any static final references, is by using Unsafe to retrieve the Field's offset and using the appropriate Unsafe method to read the primitive field or an object one. |
@franz1981 thanks for the detail. I suspect that there will no be no major driver for change until a JDK upgrade breaks the existing code. Then we will need to consider a change, probably involving a Multi-Release approach where for older JDKs things stay the same and for newer ones, we use MethodHandles or whatever works for that JDK. |
Existing code does not use Use of |
Fixed via #5046 |
MethodHandle
(3.0)
MethodHandle is available since Java 7, so API wise shouldn't be a problem.
I've been reading the discussion (can't find the issue now) about json benchmarks and how jackson already does many things dsljson etc does in terms of optimizations and was just thinking what else could potentially be done to bridge the gap (out of curiosity). 1 thing I noticed is reflection is heavily used and MethodHandle could come in as a source of improvement.
Main motivation: Afterburner is currently crippled (if not broken) in Java 9 onwards, so would be good if there was some way to bridge this performance loss without major changes.
See https://stackoverflow.com/questions/22244402/how-can-i-improve-performance-of-field-set-perhap-using-methodhandles/22337726#22337726 for more information.
Thanks!
The text was updated successfully, but these errors were encountered: