是什么决定了Class.getMethods()的返回顺序?

时间:2015-09-16 11:10:45

标签: java reflection runtime

这个问题不是寻找问题的解决方案,而是解释为什么可能出现问题(或不是!)。

Class.getMethods()的{​​{3}}说:

  

返回的数组中的元素没有排序,也没有任何特定的顺序。

问题是:我们一直在使用一个名为Javadocs的整洁的小Java模板库,可能已经有几年了,没有任何问题。这使用类似JSTL的语法将模型值注入模板。特别是,我们一直在使用这样的东西来代价:

${vendor.currency.symbol} ${order.amount}

其中第一个转换为以下内容:

vendor.getCurrency().getSymbol()

其中getCurrency()返回JMTE个对象。货币有两种获取货币符号的方法 - 一种采用特定的Locale,另一种采用默认的。

java.util.Currency

public String getSymbol()

过去18个月左右,一切运行正常,电子邮件中出现货币代码/符号。然后5天前,当我们尝试替换IllegalArgumentException时,我们开始随机${vendor.currency.symbol}

经过一些调试后,我找到了原因,深入JMTE:

for (Method method : declaredMethods) {
    if (Modifier.isPublic(method.getModifiers())
        && (method.getName().equals("get" + suffix) ||   
            method.getName().equals("is" + suffix))) {
                value = method.invoke(o, (Object[]) null);
                ....
            }
}

即,getSymbol()getSymbol(Locale)是否被调用完全取决于Class.getMethods()的返回顺序(不按任何特定顺序)。我添加了一个测试,以确保方法有0参数,我的问题解决了。

现在,由于一个奇怪的巧合,其他人碰巧在我们第一次观察到这种行为的同一天提交了public String getSymbol(Locale locale)

令人费解的是,这段代码已经运行了18个月而没有任何问题,然后突然出现这种情况。

当我创建一个测试用例时,它大约有50%的时间失败,正如人们所期望的那样(有两种匹配的方法,没有特定的顺序返回),所以我感到困惑(惊讶)它适用于18几个月和10 ^ 5次执行。 (可以想象,但不太可能,它已经失败但在随后的重试中取得了成功)。

完全出于好奇,我想知道Java运行时中是否有任何可能导致此潜在行为突然出现的内容。更令人费解的是,在同一天,其他人应该为一个成熟稳定的项目提供这种行为的解决方案 - 这可能意味着同样的潜在行为突然在其他地方实现了。

所以,问题是:有没有人知道哪些因素可能会影响Class.getMethods()返回的方法的顺序?

1 个答案:

答案 0 :(得分:2)

可以从getMethods()看到的相关Java代码显示了对缓存数据的大量检查,但最后的说法取决于此实现:

private native Method[] getDeclaredMethods0(boolean publicOnly);

因此,它依赖于虚拟机,并且仅仅因为"它很多次都是相同的而非常糟糕的想法"。

缓存肯定会影响它,因为如果它第一次正确获取,它将在随后的时间工作,除非缓存被清除(有一些软参考业务和这样下去。)