深入探讨虚拟机运行时的java线程栈帧、Java/JVM沟通(6)
2023-04-29 来源:飞速影视
如图4-9所示,假如有一个native方法,签名是(JID)I。当调用它时,signature handler会根据《Java虚拟机规范》的描述解析方法签名字符串,得到参数是this指针(long)、long、int和double,返回值为int。它会将解释器栈上这些参数放到C栈上,然后根据调用约定(x64 gcc遵循System V AMD64 ABI),将C栈上一些参数再尽可能放入寄存器。由于该调用约定可以将至多6个整数放入通用寄存器,8个浮点数放入xmm寄存器,因此本例中的4个参数都会放入寄存器。
图4-9 JNI参数处理器
除此之外,参数-XX: UseFastSignatureHandlers(默认开启)还会启用一个优化:对于不超过13个参数的native方法,signature handler会走快速路径。所谓快速路径是指JVM计算方法签名字符串得到一个64位整数方法指纹(Method Fingerprint)值,后续signature handler将不需要每次都解析签名字符串得到参数个数和类型,而是直接用方法指纹值。
同时快速路径也不会将参数放到C栈再取一些放入寄存器而是一步到位,直接放入寄存器或者C栈(如果寄存器放不下)。
上面的讨论说明如果native方法参数不超过13个,则有较高性能提升,如果参数个数在调用约定允许的寄存器范围内,可以让native调用性能到达最佳。
JavaCalls
前面提到过Java线程设置了入口后使用JavaCalls执行Java方法Thread.run()。在虚拟机中,Java代码通过JNI调用JVM方法,而JVM反过来通过JavaCalls模块调用Java方法。
JavaCalls模块可细分为call_virtual调用Java虚方法、call_static调用Java静态方法等。虚方法调用会根据对象类型进行方法决议,所以需要获取对象引用再查找实际要调用的方法,而静态方法调用直接查找要调用的方法即可。无论如何,这些方法都是先找到要调用的方法的methodHandle,然后传给如代码清单4-19所示的JavaCalls::call_helper()做实际调用:
本站仅为学习交流之用,所有视频和图片均来自互联网收集而来,版权归原创者所有,本网站只提供web页面服务,并不提供资源存储,也不参与录制、上传
若本站收录的节目无意侵犯了贵司版权,请发邮件(我们会在3个工作日内删除侵权内容,谢谢。)
www.fs94.org-飞速影视 粤ICP备74369512号