OpenJDK中的JVM_GetClassDeclaredMethods方法返回顺序

这几天有同事问到,在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最新版本。

由于函数内容较长,以几张关键代码的图来说明分析过程:

  1. 方法入口
image.png
  1. 这里访问了k->methods(),->操作符在instanceKlassHandler中被重载了,看起来比较绕
image.png
  1. 真实调用的是
image.png
  1. set_methods在类加载的时候被调用
image.png
  1. 在set_methods之前,有一个比较重要的地方,对方法进行了排序,这个顺序决定了最终的返回结果
image.png
  1. 关注一下method_comparator
image.png
  1. 最初以为是按照方法的name进行排序,结论和之前的现象不符(如果按照name排序,那么肯定是固定的),后来发现name其实是一个Symbol
image.png
  1. 继续关注上面的fast_compare函数,排序逻辑如下
image.png
  1. 到这里基本可以解释为什么MethodSorters.JVM是一个乱序了,这里比较的是地址,Symbol在传统意义的c堆中分配,因此无法保证每次独立运行时的先后顺序

你可能感兴趣的:(OpenJDK中的JVM_GetClassDeclaredMethods方法返回顺序)