【问题标题】:Does the java optimizer eliminate code whose result is not used unless an exception is thrownjava优化器是否消除了除非抛出异常否则结果不被使用的代码
【发布时间】:2018-12-17 23:18:55
【问题描述】:

考虑以下代码(java 8):

try
{
    // try to create an instance of CardExpirationDate
    AfCardExpirationDate.getInstance( anExpMonth, anExpYear);
    return true;    // expiration date is valid
}
catch ( IllegalArgumentException e )    
{
    // invalid expiration date
    return false;
}

从未使用过调用AfCardExpirationDate.getInstance的结果。我们仅在它是否抛出 IllegalArgumentException 时检查这里。

这样安全吗?或者编译时或运行时代码优化器可以去掉这样的调用吗?

【问题讨论】:

  • 创建一个像AfCardExpirationDate.isValid(anExpMonth, anExpYear) 这样的逻辑而不是实际赋予异常意义不是更简单吗?对我来说,感觉就像是对异常的滥用。
  • 它必须是一个相当粗心的优化器,假设getInstance() 不会有任何副作用。
  • 该方法可以内联,任何未使用的结果都可以丢弃。但是,触发异常的检查不能被丢弃(除非检查是static final boolean,例如断言)

标签: java compiler-optimization jit


【解决方案1】:

编译器无法对此进行优化。简单明了。

编译器无法知道对getInstance() 的毫无疑问的调用是否没有副作用。除此之外,编译器显然确实注意到您的方法有两个返回路径,因此 try/catch 很重要。

除此之外,作为一名 Java 程序员,您确实不关心 Java 源代码和类文件字节码之间发生的优化步骤。

运行时的 JIT 有 profiling 信息,当它发现该方法被频繁调用以至于值得优化时,它会在运行时将其编译为机器码。做具有上下文配置文件知识的编译器可能做的所有事情。

最后:您将 try/catch 误用于 验证 目的。这只是一种不好的做法(例如,因为相关的运行时性能成本)。如果您对 A) 代码质量和 B) 运行时性能非常认真,那么只需允许进行完整的验证,而无需依赖一些抛出的代码。

【讨论】:

  • 是的,你是对的,这段代码误用了 try/catch。但目前我别无选择,除非重新实现 AfCardExpirationDate(私有)中已经存在的验证逻辑。但感谢您的有用解释。此代码在运行时性能不是最高优先级的 ATM 中运行。
  • 有趣的设置。但我认为这仍然是一些 J2SE jre,有一些 JIT 编译器?还是小型嵌入式?
  • 这是正常的 JRE 8 发行版
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多