【发布时间】:2023-11-07 23:06:01
【问题描述】:
假设我有一个用于验证特定值的方法,例如一个方法isEven:
public static boolean isEven(int evenSize) {
return evenSize % 2 == 0;
}
我使用这种方法来验证外部输入(例如来自磁盘或来自用户)。但在那之后,我也在一个需要偶数值的方法中使用了这个方法:
public static String padToEven(int evenSize, String string) {
if (!isEven(evenSize)) { // <-- duplication of isEven method
throw new IllegalArgumentException("evenSize argument is not even");
}
if (string.length() >= evenSize) {
return string;
}
StringBuilder sb = new StringBuilder(evenSize);
sb.append(string);
for (int i = string.length(); i < evenSize; i++) {
sb.append('x');
}
return sb.toString();
}
所以基本上我们向padToEven() 提供已经验证的参数,并且使用相同的isEven 函数验证参数。 JIT 编译器(比如在 Java 版本 8 中)是否有可能找到第二个调用并将其优化掉?
您可以假设检查不依赖于动态值(即它对提供的参数值具有确定性)。除了日志语句等返回值之外,它也没有任何副作用。
【问题讨论】:
-
显然对于
isEven没关系,但例如isPrime操作上的差异可能很明显,尤其是在循环中使用时。 -
有趣的问题!然而,我怀疑在一般情况下是否有可能安全地确定这种重用。
-
@BoristheSpider 是的,可能非常棘手。 JIT 编译器有很多未知数(副作用、状态),调用也可能用很多字节码分隔。
-
这取决于您没有提到的一些事情,例如该值如何进入该函数以及这些时刻之间控制流的形状。例如,如果
padToEven在某处被调用为已经检查过isEven的函数的后代,那么它比@987654330 更容易推理(但仍然是我不期望从JVM 获得的过程间分析级别) @ 调用读取值、检查值、将其放入某个静态字段的东西,然后调用涉及padToEven的其他东西。它还取决于谓词是否可以由数字抽象域表示。
标签: java validation optimization parameters jit