OpenJDK中的JVM_GetClassDeclaredMet
2017-12-18 本文已影响0人
ssssssnake
这几天有同事问到,在junit的一些资料中,为什么不推荐使用@FixMethodOrder(MethodSorters.JVM)来做执行方法排序。
对于这个问题,API中的说法如下:
/**
* Leaves the test methods in the order returned by the JVM.
* Note that the order from the JVM may vary from run to run
*/
也就是说在每次被加载运行时,顺序是不确定的。
稍做一下分析,可以看出这个问题本质上是Class类中
getDeclaredMethods0这个本地方法返回的顺序问题。
private native Method[] getDeclaredMethods0(boolean publicOnly);
之前某项目在做webservice测试时也提到过类似的问题(运行时环境略有不同,是在J9上跑的,不过本质上没有什么差别),因此把这个问题拿来总结一下,以下代码为OpenJDK 8u最新版本。
由于函数内容较长,以几张关键代码的图来说明分析过程:
- 方法入口
- 这里访问了k->methods(),->操作符在instanceKlassHandler中被重载了,看起来比较绕
- 真实调用的是
- set_methods在类加载的时候被调用
- 在set_methods之前,有一个比较重要的地方,对方法进行了排序,这个顺序决定了最终的返回结果
- 关注一下method_comparator
- 最初以为是按照方法的name进行排序,结论和之前的现象不符(如果按照name排序,那么肯定是固定的),后来发现name其实是一个Symbol
- 继续关注上面的fast_compare函数,排序逻辑如下
- 到这里基本可以解释为什么MethodSorters.JVM是一个乱序了,这里比较的是地址,Symbol在传统意义的c堆中分配,因此无法保证每次独立运行时的先后顺序