System.out.println(5678);
このリテラルは、直接印刷文で使用されています。しかし、メモリ内のJava店舗に直接それをしないか、それが自動変数を作成し、それをそこに保存しますか?後者の場合は真であるのであれば誰でも、変数が誤って同じ変数名を使用していることをアクセスに発生した場合、何が起こるのでしょうか?
説明
どのようなJavaはボンネットの下に行うことは、完全にユーザーとプログラマから隠されています。
あなたはまだJavaコードを書いている限り、それはそれで混乱することは不可能です。あなたは、ネイティブインタフェースを介して、JVMプロセスと注入Cコード、またはそれとの相互作用をフックアップしようとした場合はもちろん別の話かもしれません。
それは実際にメモリでこれをどのように処理するか完全にJVMにもあります。メモリ管理は完全にJavaでプログラマから隠されています。
バイトコード
変数のインライン化
ことでは、私たちは(参照このスニペットの結果のバイトコードを見てみましょう、と述べたjavabytes.ioまたは使用をjavap -c Test.class
):
// Source code
public class Test {
public static void main(String [] args) {
int value = 4000;
System.out.println(value);
System.out.println(5678);
}
}
// Byte code
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: sipush 4000
3: istore_1
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: iload_1
8: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
11: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
14: sipush 5678
17: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
20: return
}
ご覧のとおり、両方のバリアントは、実際には同じです。sipush
このコマンドは、直接、すべての任意の変数の兆候は値をロードしません。
sipush
プッシュshort
それは、その後で撮像されたところから、直接スタック上にinvokevirtual
印刷メソッドを呼び出している(参照Javaバイトコード命令リストの詳細について)。
なぜ、そうではありますか?まあ、コンパイラがスマートです。これは、変数があることを考え出したvalue
目的を達成しませんし、実際には完全にそれを処分しました。それはにコードを変更System.out.println(4000)
、削除value
、完全に。
変数の存在
しかし、我々はいくつかの変数を見たいので、私たちはJavaは実行時にのみ計算できる依存関係を導入することにより、もはや変数をインライン化しないこと、それは少し複雑そうしてみましょう:
// Source code
public class Test {
public static void main(String [] args) {
int value = (int) System.currentTimeMillis();
System.out.println(value);
System.out.println(5678);
}
}
// Byte code
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J
3: l2i
4: istore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: iload_1
9: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
12: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
15: sipush 5678
18: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
21: return
}
最後に、我々はいくつかの変数のアクションを参照してください!変数に変換され、この方法によって計算されint
、次いで介して格納されていますistore_1
。次に、それは、スタック上に動的にロードされるiload_1
と、印刷メソッドに渡されました。
だから、変数を経由して、我々はに必要istore
とiload
する方法に。リテラルで、我々は直接使用する方法にそれをロードすることができますsipush
。