【问题标题】:Java dead code elimination... is this code at risk of being optimized out?Java 死代码消除...此代码是否有被优化的风险?
【发布时间】:2011-02-24 11:30:47
【问题描述】:

所以,我使用的 API 在某些方面有点不友好。基本上,这个 API 创建了一个可以稍后获取的资源。当我们稍后去获取它时,这个资源可能仍然存在,也可能不存在。

要获取之前创建的资源,您必须使用这样的结果 guid:

String resultKey = "12345";
PersistedResult r = mFactory.getPersistedResult(resultKey);

现在,这里的棘手之处在于 getPersistedResult 在使用无效 guid 调用时不会引发异常...PersistedResult 是一个惰性加载器,只有在调用其中一个方法时才会失败(导致对象自行加载)。

所以,为了尝试确定资源是否有效,我正在执行以下操作:

PersistedResult r = null;

if (!StringUtils.isEmpty(resultKey)) {
    try {
       r = mFactory.getPersistedResult(resultKey);
       r.getResultCount(); // Triggers exception if result key was invalid.    
    } catch (Exception e) {
       // handle exception
    }
 }

我对@9​​87654325@ 的调用是否有被优化的风险,因为我没有使用该值?

在PersistedResult 上调用任何方法都会转到外部数据库,以防万一。

谢谢

【问题讨论】:

  • try-catch 是否只在 r.getResultCount 附近?

标签: java optimization compiler-construction


【解决方案1】:

编译器不能假定 getResultCount() 没有副作用——因此它不能删除调用。

【讨论】:

  • 并不是那么简单。虽然它不能假设,但理论上它可以证明它没有副作用。但另一点是副作用可能包括抛出异常,或任何其他可能对程序结果产生明显影响的事情。
  • 为了迂腐,这里的原始海报明确表示 getResultCount() 确实有副作用。因此,如果编译器足够聪明地进行此类证明,它将得出正确的结论。换句话说,如果它不够聪明地去做这些事情,那么做出假设就是错误的。
  • 万斯,谢谢,是的,这就是我的假设,我只是想确定一下。死代码消除似乎是一种非常危险的优化技术,因为似乎大多数代码都有副作用的可能性。我真的不确定 JVM/javac 如何确定什么有副作用,什么没有。
  • @Polaris878 “死代码”是通过正常方式确定为无法访问的代码,而不是具有未使用值的代码。例如if (false) { /* everything here would be considered dead code */ }.
【解决方案2】:

不,为什么会这样? getResultCount 不会被内联,在这种情况下它是一个黑盒并且必须执行,因为它可以做任何事情,或者它会被内联,在这种情况下编译器可以看到它可能会抛出异常,并且将执行该操作。

它有一个返回值这一事实并不重要。如果这是一个因素,那么如果调用者不检查其返回值,那么任何复杂的函数都将面临被优化的风险。

【讨论】:

  • 那是我不确定的……Java 中的死代码消除有多贪婪?这些方法没有检查异常......它们都是运行时异常。同样,不确定这是否重要?
【解决方案3】:

运行时(或编译时,相同)的优化不允许给您带来与没有优化时(除了运行时或内存节省)不同的结果。如果此处由于优化而没有引发您的异常,则这绝对是另一种行为,因此将是一个错误。

(请注意,在多线程环境中,这在考虑不同线程之间的关系时会稍微宽松一些。)

【讨论】:

    【解决方案4】:

    没有。因为优化不能改变代码的语义。

    【讨论】:

      猜你喜欢
      • 2012-01-18
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多