Java反射慢有什么替换_⽐Java反射更快的替代⽅案
invokedynamic
字节码指令是⽤来避免⾮常慢的反射的技术的实现者。简⽽⾔之,invokedynamic(或“indy”)是java7中引⼊的最伟⼤的东西,⽬的是为通过动态⽅法调⽤在JVM之上实现动态语⾔铺平道路。后来它还允许java8中的lambda表达式和⽅法引⽤以及java9中的字符串连接从中受益。
简⽽⾔之,下⾯我将利⽤lambdametfactory和MethodHandle来动态创建函数的实现。它的单个⽅法使⽤lambda body内部定义的代码委托对实际⽬标⽅法的调⽤。
这⾥讨论的⽬标⽅法是实际的getter⽅法,它可以直接访问我们要读取的字段。另外,我应该说,如果您⾮常熟悉Java8中出现的好东西,您会发现下⾯的代码⽚段⾮常容易理解。否则,乍⼀看可能会很棘⼿。
看看⾃制的JavaBean
下⾯的⽅法是⽤于从JavaBean字段读取值的实⽤程序。它使⽤JavaBean对象和⼀个单独的fieldA,甚⾄是⽤句点分隔的嵌套字段,例如:stedJavaBean.fieldAjavabean是干什么的
为了获得最佳性能,我缓存了动态创建的函数,这是读取给定字段名内容的实际⽅式。因此,在getCachedFunction⽅法内部,正如您在上⾯看到的,有⼀个利⽤类值进⾏缓存的快速路径,还有⼀个缓慢的createAndCacheFunction路径,只有在到⽬前为⽌没有缓存的情况下才会执⾏。
慢路径基本上将委托给createFunctions⽅法,该⽅法通过使⽤Function::and then链接返回要缩减的函数列表。当getFieldBean()调⽤嵌套的JavaBean()时。最后,在链接之后,我们只需将简化后的函数放⼊缓存中调⽤cacheAndGetFunction⽅法。
在函数创建的慢路径上再深⼊⼀点,我们需要通过拆分field path变量来单独导航,如下所⽰:
上⾯的createFunctions⽅法将单个字段名及其类持有者类型委托给createFunction⽅法,该⽅法将根据
此元组映射由createTupleWithReturnTypeAndGetter与createCallSite⽅法⼀起完成,如下所⽰:
使⽤invokedynamic⽅法的最坏场景⽐其他两个库中最快的场景快得多。这是⼀个巨⼤的区别,如果你对结果有疑问,你可以随时下载源代码,随意玩玩。
现在,让我们看看相同的基准测试在Graalvmee1.0.0-rc9中的表现
总结
最⼤的区别是因为JIT编译器⾮常了解CallSite和MethodHandle,并且知道如何将它们内联起来,⽽不是反射⽅法。另外,你可以看到GraalVM是多么有前途。它的编译器做了⼀个真正了不起的⼯作,能够极⼤地提⾼反射⽅法的性能。
如果你很好奇,想继续玩下去,我建议你从我的Github中获取源代码。请记住,我并不⿎励您⾃⼰制作JavaBeanUtil并在⽣产中使⽤。我的⽬的是简单地展⽰我的实验和invokedynamic的可能性。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。