为什么在 Java 字节码中跳转而不是返回?

dmi*_*oso 2 java jvm bytecode java-bytecode-asm jvm-bytecode

背景

我编译了以下方法:

public static final boolean equalTo(final int x, final int y) {
    return x == y;
}
Run Code Online (Sandbox Code Playgroud)

可以javap看到为其生成了以下字节码:

  public static final boolean equalTo(int, int);                                                                                                                                                                 
    descriptor: (II)Z                                                                                                                                                                                            
    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL                                                                                                                                                            
    Code:                                                                                                                                                                                                        
      stack=2, locals=2, args_size=2                                                                                                                                                                             
         0: iload_0                                                                                                                                                                                              
         1: iload_1                                                                                                                                                                                              
         2: if_icmpne     9                                                                                                                                                                                      
         5: iconst_1                                                                                                                                                                                             
         6: goto          10                                                                                                                                                                                     
         9: iconst_0                                                                                                                                                                                             
        10: ireturn                                                                                                                                                                                              
      LineNumberTable:                                                                                                                                                                                           
        line 72: 0                                                                                                                                                                                               
      StackMapTable: number_of_entries = 2                                                                                                                                                                       
        frame_type = 9 /* same */                                                                                                                                                                                
        frame_type = 64 /* same_locals_1_stack_item */                                                                                                                                                           
          stack = [ int ]                                                    
Run Code Online (Sandbox Code Playgroud)

我编写了ASM来创建相同的字节码,并且还通过goto 10ireturn. 它可以忽略不计,但这也减少了 的大小,StackMapTable因为它消除了跳转。

问题

我知道“这只是字节码”,并不表示机器将做什么,但是为什么编译器goto 10在可以简单地发出时却发出信号ireturn

bon*_*ill 6

前端编译器使用简单的模式生成代码,并且它们依靠优化过程来清理东西。在生成表达式时x == y,编译器并不“知道”接下来是 return 语句。它可能会检查这一点,但是这个额外的步骤可以通过某种窥视孔优化器轻松处理。

窥孔优化器的好处是它可以执行级联优化,即一个优化的结果可以反馈到下一个优化。生成表达式的代码x == y实际上没有任何方法可以在不增加更多复杂性的情况下执行超过一个优化步骤的任何操作。

java 编译器曾经有一个优化功能,但它被放弃了,取而代之的是 HotSpot,它可以执行更强大的优化。在 java 编译器中执行优化会减慢它的速度,并且不会真正改善一切。