ADT*_*DTC 6 java runtime execution operator-precedence compiler-optimization
我在JLS 15.7.4和15.12.4.2上做了一些阅读,但它并不能保证不会有任何编译器/运行时优化会改变评估方法参数的顺序.
假设以下代码:
public static void main (String[] args) {
MyObject obj = new MyObject();
methodRelyingOnEvalOrder(obj, obj.myMethod());
}
public static Object methodRelyingOnEvalOrder(MyObject obj, Object input) {
if (obj.myBoolean())
return null;
else
return input;
}
Run Code Online (Sandbox Code Playgroud)
是否保证编译器或运行时不会进行错误优化,如下所示?这种优化可能看起来是正确的,但是当评估顺序很重要时,这是错误的.
在调用obj.myMethod改变将返回的值的情况下,首先调用obj.myBoolean是至关重要的,obj.myMethod因为methodRelyingOnEvalOrder需要首先进行此更改.
//*******************************
//Unwanted optimization possible:
//*******************************
public static void main (String[] args) {
MyObject obj = new MyObject();
methodRelyingOnEvalOrder(obj);
}
public static Object methodRelyingOnEvalOrder(MyObject obj) {
if (obj.myBoolean())
return null;
else
return obj.myMethod();
}
//*******************************
Run Code Online (Sandbox Code Playgroud)
如果可能,请显示支持您的答案的一些来源或Java文档.
注意:请不要要求重写代码.这是一个特殊情况,我在质疑评估顺序保证和编译器/运行时优化保证.的执行obj.myMethod必须在发生main的方法.
您提到的JLS(15.7.4)确实保证:
每个参数表达式似乎在其右边的任何参数表达式的任何部分之前被完全计算.
以及15.12.4.2:
然后使用参数值继续评估,如下所述.
"似乎"部分允许一些优化,但它不能是可见的.在 "评估然后继续" 之前评估所有参数的事实表明,在方法执行之前,参数确实已经完全评估.(或者至少,这是可见的结果.)
例如,如果你有以下代码:
int x = 10;
foo(x + 5, x + 20);
Run Code Online (Sandbox Code Playgroud)
有可能优化它来同时评估x + 5和x + 20平行:你无法检测到这种情况.
但是在您给出的情况下,您将能够检测到调用后obj.myMethod发生的调用obj.myBoolean(),因此根本不是有效的优化.
简而言之:你可以假设一切都会以明显的方式执行.
除了参数评估顺序之外,在调用方法时执行的步骤概述及其顺序,在第15.12.4节中进行了解释.方法调用的运行时评估,清楚地表明在执行方法代码之前执行所有参数评估.引用:
在运行时,方法调用需要五个步骤.首先,可以计算目标参考.其次,评估参数表达式.第三,检查要调用的方法的可访问性.第四,找到要执行的方法的实际代码.第五,创建新的激活帧,如果需要则执行同步,并且将控制转移到方法代码.
您提出的仅在控制转移到方法代码后才评估参数的情况是不可能的.
| 归档时间: |
|
| 查看次数: |
1939 次 |
| 最近记录: |