1

Does javac leave out private methods if they are inlined? For example

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

But what if this method is then accessed by reflection?

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

How does the compiler know whether to inline the method and remove it or not?

vikarjramun
  • 1,042
  • 12
  • 30
  • 3
    What makes you think this method is being inlined by the compiler? It does no inlining. Inlining might happen at runtime, in the JIT compiler. – JB Nizet Oct 21 '17 at 15:32
  • 1
    You can try it out for yourself by disassembling the compiled class using `javap`. It will most likely not discard the method. – Jesper Oct 21 '17 at 15:33
  • 1
    Compiler optimizations never change behavior. – 4castle Oct 21 '17 at 15:33
  • *"Does `javac` leave out private methods ..."* - No. Not under any circumstances. And `javac` doesn't do inlining anyway. (You can check both of these things for yourself using `javap`.) – Stephen C Oct 21 '17 at 15:37

1 Answers1

2

I have followed user Jesper's suggestion and used javap on this code:

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!");
    }
}

Method sayHello is used and bananas is not.

The result of running javap with the -p parameter on the compiled class with Java 8 is:

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
}

The method bananas is mentioned in the byte code comments (sayHello is there too).

Will compilers optimize out unused private methods?

Not really.

gil.fernandes
  • 12,978
  • 5
  • 63
  • 76
  • 1
    @JB Nizet: shame on me. Many thanks for pointing out that the -p parameter was missing. You deserve some credit. – gil.fernandes Oct 21 '17 at 16:04
  • Thanks for your answer. I never realized that javac didn't do any optimizing! Seems like missed opportunity though – vikarjramun Oct 21 '17 at 19:58
  • Seems Android's Java-op-code optimizations work better by far, I mean, even always false if-block's code is removed (beside unused methods being removed). – Top-Master May 27 '22 at 08:02