是否有Java编译器或JVM忽略优化语句?

是否有Java编译器或JVM忽略优化语句?,java,optimization,Java,Optimization,假设我们有下面的陈述 arrayList.size(); 这句话本身毫无用处。出于优化目的,任何Java编译器或JVM都会忽略此语句吗 实际上,编译器或JVM假定语句没有副作用,因此会将其删除以进行优化 如评论中所述,它并不完全是一个no op:至少,它必须执行空检查。此外,ArrayList的子类可能工作方式不同。理论上,他们甚至可以从数据库或类似的地方获取数据。通常,没有人会为此将ArrayList子类化,但这样的列表实现是有意义的 编译器(JIT,而不是javac)必须能够证明它确实没

假设我们有下面的陈述

arrayList.size(); 
这句话本身毫无用处。出于优化目的,任何Java编译器或JVM都会忽略此语句吗


实际上,编译器或JVM假定语句没有副作用,因此会将其删除以进行优化

如评论中所述,它并不完全是一个no op:至少,它必须执行空检查。此外,
ArrayList
的子类可能工作方式不同。理论上,他们甚至可以从数据库或类似的地方获取数据。通常,没有人会为此将
ArrayList子类化,但这样的
列表
实现是有意义的

编译器(JIT,而不是javac)必须能够证明它确实没有副作用。通常情况下,它非常简单

  • 它知道是否有任何被重写的
    ArrayList.size()
    .1实现
  • 如果没有,那么它会看到它是一个简单的getter并将其内联
  • 这将问题归结为一个无用的字段加载,它将简化为空检查
  • 如果以前执行过空检查(例如,由于以前的无用语句:D),也可以消除空检查
  • 否则,如果
    arrayList
    是循环不变量,它可能会移出循环
出于优化目的,任何Java编译器或JVM都会忽略此语句吗

所以我认为这很有可能发生


1这可能会在以后随着此类类的加载而改变,然后将进行去优化。
2假设它决定值得优化。

3如果该方法已经超过内联限制,例如,由于糟糕的编码风格或其他内联,则此操作可能会失败。

如注释中所述,它并不完全是无操作:至少,它必须执行空检查。此外,
ArrayList
的子类可能工作方式不同。理论上,他们甚至可以从数据库或类似的地方获取数据。通常,没有人会为此将
ArrayList子类化,但这样的
列表
实现是有意义的

编译器(JIT,而不是javac)必须能够证明它确实没有副作用。通常情况下,它非常简单

  • 它知道是否有任何被重写的
    ArrayList.size()
    .1实现
  • 如果没有,那么它会看到它是一个简单的getter并将其内联
  • 这将问题归结为一个无用的字段加载,它将简化为空检查
  • 如果以前执行过空检查(例如,由于以前的无用语句:D),也可以消除空检查
  • 否则,如果
    arrayList
    是循环不变量,它可能会移出循环
出于优化目的,任何Java编译器或JVM都会忽略此语句吗

所以我认为这很有可能发生


1这可能会在以后随着此类类的加载而改变,然后将进行去优化。
2假设它决定值得优化。

3如果该方法已经超过内联限制,例如,由于糟糕的编码风格或其他内联,则此操作可能失败。

可能。为什么不测试它并查看类的字节码呢?Java编译器可能不能;如果
arrayList
是某个子类,其
size
方法有副作用,该怎么办?愚蠢,是的,但仍然有道理。但是,一些JIT编译器可能会消除它。它真的没有任何作用吗?函数调用可能有副作用。@PlatinumAzure这正是我想知道的。是否有编译器通过假设没有副作用来做出这样的决定。根据代码的上下文,可能无法证明调用没有副作用。编译器不能只是假设,它必须证明它没有副作用。一个副作用(尽管经常被忽略)是,它至少执行空检查。为什么不测试它并查看类的字节码呢?Java编译器可能不能;如果
arrayList
是某个子类,其
size
方法有副作用,该怎么办?愚蠢,是的,但仍然有道理。但是,一些JIT编译器可能会消除它。它真的没有任何作用吗?函数调用可能有副作用。@PlatinumAzure这正是我想知道的。是否有编译器通过假设没有副作用来做出这样的决定。根据代码的上下文,可能无法证明调用没有副作用。编译器不能只是假设,它必须证明它没有副作用。一个副作用(尽管经常被忽略)是,它至少执行空检查。