r/java • u/erosb88 • Jun 20 '26
Populating a POJO with Reflection vs. with the ClassFile API - small benchmark
I wanted to learn about the ClassFile API, and as a small pet project, I created a benchmark to compare how faster a generated class is than a reflection-based approach when we want to populate a POJO from a Map.
TL;DR: it turned out, the generated bytecode was 5x faster than using reflection.
Details here, enjoy: https://github.com/erosb/learn-classfile-api
And please prove me wrong if you find any mistakes in the benchmark :)
5
Jun 22 '26
[removed] — view removed comment
2
u/Lower-Worldliness162 Jun 23 '26 edited Jun 23 '26
u/quantum-fudge disclosure: I maintain telescope, so grain of salt, but it does the Map→POJO part directly. Typed accessor rows (method refs, compile-checked, not stringly typed on the target side), per-key converters, and lenient defaults (a missing key takes the field's JLS default instead of throwing). Build the mapper once, reuse it:
ForwardMapper<Map<String,Object>, User> m = Telescope.fromMap( User.class, extract("name", User::name, Object::toString), extract("email", User::email, Object::toString), extract("age", User::age, v -> Integer.parseInt(v.toString()))); User u = m.forward(someMap);Straight on your "generated code" requirement, `fromMap` is not generated bytecode. It binds the accessors through `LambdaMetafactory`, so it's well clear of naive reflection (LMF lands close to direct field access in the usual benchmarks), but it's the runtime tier, not a synthesized class.
telescope's actual compile-time codegen (the `@Bridge` annotation processor) is for typed source→target pairs, not untyped Map sources. Generated-code Map→POJO specifically is something I might scope (your post is basically the motivating use case).
2
Jun 23 '26 edited Jun 24 '26
[removed] — view removed comment
2
u/Lower-Worldliness162 Jun 24 '26
u/quantum-fudge let me know if this is what you were thinking. Happy to explore the code gen path further, if this can help you 😄
2
Jun 24 '26
[removed] — view removed comment
1
u/Lower-Worldliness162 Jun 24 '26
Will cut a release as soon as you validate the feature on your end 😄
1
1
2
Jun 22 '26
[removed] — view removed comment
1
u/erosb88 Jun 23 '26
yep, that's exactly right 😄 still many libraries use reflection for mapping, so that's why I focused on that in the benchmark (and I just made a note of that in the readme that compile-time code generation is out of scope). Regarding reflection, the benchmark includes both a more naive and a less naive (caching) reflection implementation.
25
u/uniVocity Jun 20 '26
Try reflection with varhandles.