私は、Javaを学ぶすべての学生がこの質問に精通していると思います。古典的なインタビューの質問として、私は本当に長年働いた後は非常に難しい質問だと思います。インターネットでこの質問について議論している多くの人々をまだ見ることができます。なかでも、長年働いてきた方々の多くが紛争を抱えており、その点についてお話しする必要があると思います。
メソッドエリアから話す
メソッド領域には定数プールが存在し、jdk1.7バージョンの前後でメソッド領域が大幅に変更されているため、最初にメソッド領域の進化について説明します。
jdk1.7バージョンより前は、定数プールはメソッド領域に存在していました。メソッド領域はヒープの論理的な部分でした。非ヒープと呼ばれる名前がありました。
バージョン1.7は、文字列定数プールをヒープに配置します。
1.8以降、永続的な生成は削除され、メソッド領域の概念は保持され、メソッド領域の実装はメタスペースに変更され、定数プールはまだヒープ内にあります。
JDKのバージョンによって以下の記事の内容が発散しないという理由だけで、メソッド領域が変更されたと言うのはなぜですか。以下の内容は、jdk1.8バージョンに基づいて説明されます。
String s = new String(“ xyz”);
最初にコードが来る
public class Test {
public static void main(String[] args) {
String s = "xyz";
}
}
次に、javacを使用してコードをコンパイルし、次にjavapを使用して逆コンパイルし、javap-cテストを実行します。
結果から、ldcコマンドは定数プールに「xyz」オブジェクトを作成し、それをオペランドスタックの最上位にプッシュし、astoreはそれをローカル変数に保存して、戻り値を返します。
次に、2番目のインタビューの質問のコードを見てください
public class Test {
public static void main(String[] args) {
String s = new String("xyz");
}
}
同じ逆コンパイル分析
明らかに、newがStringオブジェクトを作成し、ldcが定数プールに「xyz」stringオブジェクトを作成することがわかります。次に、invokespecialがコンストラクターを実行し、astore_1を割り当てて、を返します。
上記の2つの例から、String s = new String( "xyz");が2つのオブジェクトを作成し、3つのオブジェクトが1つのオブジェクトと呼ばれるという回答があります。
xyzが存在する場合は2が作成され、存在しない場合は3(参照sを含む)という回答もあります。もう一度テストしてみましょう。
public class Test {
public static void main(String[] args) {
String s = "xyz";
String s2 = new String("xyz");
}
}
ここから、これが例1と2の組み合わせであることは明らかですが、2つのldcの後の**#2 **に注意してください。#はインデックスを表し、2番目の新しい文字列( "xyz")を示します。 xyzオブジェクトは再作成されません。
いくつかの一般的な命令ニーモニックの意味:
- いいえ、何もしません。
- aconst_null、nullをスタックの一番上にプッシュします。
- iconst_i(可変番号)、intタイプiをスタックの一番上にプッシュします。同様に、lconst_0とfconst_0があり、それが何を意味するかを知っておく必要があります
- ldcは、int、float、またはStringタイプの定数値を定数プールからスタックの最上位にプッシュします。
- iload、指定されたint型ローカル変数をスタックの一番上にプッシュします。
- istoreは、スタックの最上位にあるint型の値を指定されたローカル変数に格納します。同様に、astore_iは、スタックの最上位参照値をi番目のローカル変数に格納することを表します。
- dup、スタックの最上位の値をコピーし、コピーした値をスタックの最上位にプッシュします。
- invokevirtual、インスタンスメソッドを呼び出します。
- invokespecialは、スーパークラス構築メソッド、インスタンス初期化メソッド、プライベートメソッドを呼び出します。
- invokestatic、静的メソッドを呼び出します。
- invokeinterface、interfaceメソッドを呼び出します。
- invokedynamic、動的リンクメソッドを呼び出します。
- new、オブジェクトを作成し、その参照値をスタックの一番上にプッシュします。
総括する
いくつのオブジェクトが作成されますか?
-
xyzが存在せず、参照がオブジェクトとしてカウントされる場合、3つあります。
-
xyzが存在せず、参照がオブジェクトでない場合、2つあります。
-
xyzが存在し、参照がオブジェクトとしてカウントされる場合、2つあります。
-
xyzが存在し、参照がオブジェクトでない場合、それは1です。
もちろん、引用は絶対にターゲットではないと思います。最終的な答えは1または2である必要があります。正直なところ、このインタビューの質問は、主要なインタビューの質問に表示されるべきではありません。
さらに、逆コンパイルされたバイトコードの説明がわからない場合は、パブリックアカウントに従い、キーワード111に返信して、「Java仮想マシン仕様」の電子書籍を入手してください。