次のファイルを(を使用してjavap -c
)逆アセンブルすると、バイトコードにコンパイルするときに1.7.0コンパイラによってファイルが削除されないことがわかります。
public class Program
{
public static class Message extends Object {}
public interface ILogger {
void log(Message m);
}
public static class Logger implements ILogger {
public void log(Message m) { /* empty */ }
}
public static void main(String[] args) {
ILogger l = new Logger();
l.log((Message)null); // a)
l.log(new Message()); // b)
}
}
結果は以下のとおりです。重要なビットは、13行目と26行目の呼び出しです。
Compiled from "Program.java"
public class Program {
public Program();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class Program$Logger
3: dup
4: invokespecial #3 // Method Program$Logger."<init>":()V
7: astore_1
8: aload_1
9: aconst_null
10: checkcast #4 // class Program$Message
13: invokeinterface #5, 2 // InterfaceMethod Program$ILogger.log:(LProgram$Message;)V
18: aload_1
19: new #4 // class Program$Message
22: dup
23: invokespecial #6 // Method Program$Message."<init>":()V
26: invokeinterface #5, 2 // InterfaceMethod Program$ILogger.log:(LProgram$Message;)V
31: return
}
編集:ただし、@ mikeraが指摘したように、プログラムの実行時にJITコンパイラーがさらに最適化を行う可能性があります。これにより、呼び出しを排除できる可能性があります。残念ながら、詳細についてはコメントできません。
補足:ホットスポットJVMで使用されるパフォーマンス手法を扱ったこのリンクに興味があるかもしれません。
https://wikis.oracle.com/display/HotSpotInternals/PerformanceTechniques