在优化过程中Java内联方法会不会? [英] Would Java inline method(s) during optimization?

查看:161
本文介绍了在优化过程中Java内联方法会不会?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道JVM / javac是否足够智能转

I wonder if JVM/javac is smart enough to turn

// This line...
string a = foo();

string foo()
{
  return bar();
}

string bar()
{
  return some-complicated-string computation;
}

进入

string a = bar();

或者在发布案例中删除对foo()的不必要调用(因为无法访问的代码):

Or strip unnecessary call to foo() in release case (because unreachable code):

string a = foo(bar());

// bar is the same
...

string foo(string b)
{
  if (debug) do-something-with(b);
}

我的感觉是第一个例子是肯定的,而且不太确定第二个,但有人可以给我一些指示/链接来确认吗?

My feeling is yes for the first example and "not so sure" for the second one, but could anyone give me some pointers/links to confirm that?

推荐答案

javac 将显示字节码,它是生成字节码的原始Java程序的忠实表示(除非在某些情况下可以优化:常量折叠死码消除的)。但是,JVM在使用JIT编译器时可以执行优化。

javac will present bytecode that is a faithful representation of the original Java program that generated the bytecode (except in certain situations when it can optimize: constant folding and dead-code elimination). However, optimization may be performed by the JVM when it uses the JIT compiler.

对于第一个场景,看起来JVM支持内联(参见 Methods 此处并查看这里是关于JVM的内联示例。)

For the first scenario it looks like the JVM supports inlining (see under Methods here and see here for an inlining example on the JVM).

我找不到任何由 javac <执行的方法内联的示例/ code>本身。我尝试编译一些示例程序(类似于您在问题中描述的程序),即使它是 final ,它们似乎都没有直接内联方法。似乎这些优化是由JVM的JIT编译器完成的,而不是由 javac 完成的。 Methods 这里似乎是HotSpot JVM的JIT编译器而不是 javac

I couldn't find any examples of method inlining being performed by javac itself. I tried compiling a few sample programs (similar to the one you have described in your question) and none of them seemed to directly inline the method even when it was final. It would seem that these kind of optimizations are done by the JVM's JIT compiler and not by javac. The "compiler" mentioned under Methods here seems to be the HotSpot JVM's JIT compiler and not javac.

从我所看到的, javac 支持死代码消除(参见第二种情况的示例)和常量折叠的。在常量折叠中,编译器将预先计算常量表达式并使用计算值而不是在运行时执行计算。例如:

From what I can see, javac supports dead-code elimination (see the example for the second case) and constant folding. In constant folding, the compiler will precalculate constant expressions and use the calculated value instead of performing the calculation during runtime. For example:

public class ConstantFolding {

   private static final int a = 100;
   private static final int b = 200;

   public final void baz() {
      int c = a + b;
   }
}

编译为以下字节码:

Compiled from "ConstantFolding.java"
public class ConstantFolding extends java.lang.Object{
private static final int a;

private static final int b;

public ConstantFolding();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public final void baz();
  Code:
   0:   sipush  300
   3:   istore_1
   4:   return

}

请注意,字节码有一个 sipush 300 而不是 aload getfield s和 iadd 300 是计算值。 私有最终变量的情况也是如此。如果 a b 不是静态的,则生成的字节码将为:

Note that the bytecode has an sipush 300 instead of aload's getfields and an iadd. 300 is the calculated value. This is also the case for private final variables. If a and b were not static, the resulting bytecode will be:

Compiled from "ConstantFolding.java"
public class ConstantFolding extends java.lang.Object{
private final int a;

private final int b;

public ConstantFolding();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   bipush  100
   7:   putfield    #2; //Field a:I
   10:  aload_0
   11:  sipush  200
   14:  putfield    #3; //Field b:I
   17:  return

public final void baz();
  Code:
   0:   sipush  300
   3:   istore_1
   4:   return

}

此处还使用 sipush 300

对于第二种情况(死代码消除),我使用了以下测试程序:

For the second case (dead-code elimination), I used the following test program:

public class InlineTest {

   private static final boolean debug = false;

   private void baz() {
      if(debug) {
         String a = foo();
      }
   }

   private String foo() {
      return bar();
   }

   private String bar() {
      return "abc";
   }
}

给出以下字节码:

Compiled from "InlineTest.java"
public class InlineTest extends java.lang.Object{
private static final boolean debug;

public InlineTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

private void baz();
  Code:
   0:   return

private java.lang.String foo();
  Code:
   0:   aload_0
   1:   invokespecial   #2; //Method bar:()Ljava/lang/String;
   4:   areturn

private java.lang.String bar();
  Code:
   0:   ldc #3; //String abc
   2:   areturn

}

As你可以看到,在 baz 中根本没有调用 foo ,因为里面的代码if block实际上是死。

As you can see, the foo is not called at all in baz because the code inside the if block is effectively "dead".

Sun(现在的Oracle)HotSpot JVM结合了字节码的解释以及JIT编译。当字节码呈现给JVM时,代码最初被解释,但JVM将监视字节码并挑选出经常执行的部分。它将这些部分转换为本机代码,以便它们运行得更快。对于那些频繁使用的字节码,此编译未完成。这也是因为编译有一些开销。所以这真的是一个权衡问题。如果您决定将所有字节码编译为本机代码,那么代码可能会有很长的启动延迟。

Sun's (now Oracle's) HotSpot JVM combines interpretation of the bytecode as well as JIT compilation. When bytecode is presented to the JVM the code is initially interpreted, but the JVM will monitor the bytecode and pick out parts that are frequently executed. It coverts these parts into native code so that they will run faster. For piece of bytecode that are not used so frequently, this compilation is not done. This is just as well because compilation has some overhead. So it's really a question of tradeoff. If you decide to compile all bytecode to nativecode, then the code can have a very long start-up delay.

除了监视字节码之外,JVM还可以执行字节码的静态分析,因为它正在解释并加载它以执行进一步优化。

In addition to monitoring the bytecode, the JVM can also perform static analysis of the bytecode as it is interpreting and loading it to perform further optimization.

如果您想知道JVM执行的特定类型的优化,这个页面在Oracle很漂亮很有帮助。它描述了HotSpot JVM中使用的性能技术。

If you want to know the specific kinds of optimizations that the JVM performs, this page at Oracle is pretty helpful. It describes the performance techniques used in the HotSpot JVM.

这篇关于在优化过程中Java内联方法会不会?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆