这个问题不是寻找问题的解决方案,而是解释为什么可能出现问题(或不是!).
Class.getMethods()的Javadocs说:
The elements in the array returned are not sorted and are not in any particular order.
问题是:我们已经使用了一个简洁的小型Java模板库,名为JMTE,可能已经有几年了,没有任何问题.这使用类似JSTL的语法将模型值注入模板.特别是,我们一直在使用这样的东西来代价:
${vendor.currency.symbol} ${order.amount}
第一个转换为以下内容:
vendor.getCurrency().getSymbol()
其中getCurrency()返回java.util.Currency对象.货币有两种获取货币符号的方法 – 一种采用特定的Locale,另一种采用默认的.
在过去的18个月左右,一切运行正常,电子邮件中出现货币代码/符号.然后5天前,当我们尝试替换${vendor.currency.symbol}时,我们开始抛出一个随机的IllegalArgumentException
经过一些调试后,我发现了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参数,我的问题解决了.
现在,由于一个奇怪的巧合,其他人碰巧在我们第一次观察到这种行为的同一天提交了identical fix.
令人费解的是,这段代码已经运行了18个月而没有任何问题,然后突然出现这种行为.
当我创建一个测试用例时,它大约有50%的时间失败,正如人们所期望的那样(有两种匹配的方法,没有特定的顺序返回),所以我很困惑(惊讶)它工作了18个月和10 ^ 5处决. (可以想象,但不太可能,它已经失败但在随后的重试中取得了成功).
纯粹出于好奇,我想知道Java运行时中是否有任何可能导致这种潜在行为突然出现的东西.更令人费解的是,在同一天,其他人应该为一个成熟稳定的项目提供这种行为的解决方案 – 这可能意味着同样的潜在行为突然在其他地方实现了.
所以,问题是:有没有人知道哪些因素可能会影响Class.getMethods()返回的方法的顺序?
最佳答案 从getMethods()可以看到的相关Java代码显示了很多对缓存数据的检查,但最后的说法取决于这个实现:
private native Method [] getDeclaredMethods0(boolean publicOnly);
因此,它依赖于VM,并且仅仅因为“它很多次都是相同的”而非常缺乏信任该命令的想法.
缓存肯定会影响它,因为如果它第一次正确获取,它将在随后的时间工作,除非缓存被清除(有一些软参考业务等等).