【问题标题】:Will compilers optimize out unused private methods?编译器会优化未使用的私有方法吗?
【发布时间】:2017-10-21 15:30:57
【问题描述】:

如果它们是内联的,javac 是否会遗漏私有方法? 例如

public class Test {
  public static void main(String[] args){
    System.out.println(sayHello());
  }
  private static String sayHello(){
    return "Hello World";
  }
}

但是如果这个方法被反射访问呢?

 System.out.println(Test.class.getMethod("sayHello").invoke(null));

编译器如何知道是否内联方法并删除它?

【问题讨论】:

  • 是什么让你觉得这个方法被编译器内联了?它没有内联。内联可能发生在运行时,在 JIT 编译器中。
  • 您可以通过使用javap 反汇编编译的类来自己尝试一下。它很可能不会丢弃该方法。
  • 编译器优化永远不会改变行为。
  • “javac 是否遗漏了私有方法...” - 不,在任何情况下都不会。而javac 无论如何也不做内联。 (您可以使用javap 自己检查这两件事。)

标签: java javac compiler-optimization private-methods


【解决方案1】:

我听从了用户 Jesper 的建议,并在这段代码上使用了 javap:

package stackoverflow;

public class CompilerOptimize {
    public static void main(String[] args){
        System.out.println(sayHello());
    }

    private static String sayHello(){
        return "Hello World";
    }

    private static void bananas() {
        System.out.println("Monkey!");
    }
}

使用方法sayHello,不使用bananas。

在用Java 8编译的类上运行带有-p参数的javap的结果是:

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

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: invokestatic  #3                  // Method sayHello:()Ljava/lang/String;
       6: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       9: return

  private static java.lang.String sayHello();
    Code:
       0: ldc           #5                  // String Hello World
       2: areturn

  private static void bananas();
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #6                  // String Monkey!
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

字节码cmets中提到了bananas方法(sayHello也有)。

编译器会优化未使用的私有方法吗?

不是真的。

【讨论】:

  • @JB Nizet:真丢脸。非常感谢您指出缺少 -p 参数。你值得称赞。
  • 感谢您的回答。我从来没有意识到 javac 没有做任何优化!似乎错过了机会
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2016-06-01
  • 2011-10-30
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多