基本的な知識-JVMについて話します(++ iとi ++の違いを理解するには、バイトコードファイルを参照してください。メモリを使用して、String str = "11"が2つのOOPを生成する方法を確認してください)

1.クラスのロード方法

ここに画像の説明を挿入

.1.1 javaファイルjavacはバイトコード命令セットファイルにコンパイルされ、javap -cTest.classは関連するバイトコード命令を見ることができます。
1.2クラス読み込みサブシステムは、クラスファイルをInstanceKlassメタデータに解析し、メソッド領域に配置します
。1.3JDK8の後、旧世代のメタスペースはキャンセルされ、旧世代に置き換えられます。1.4
メソッド領域は、インターフェイスの旧世代のメタスペースとして理解できます。
1.5メソッドを実装するエリアヒープは共有メモリエリアです。メソッドエリアには主にクラスメタデータ、定数プール、静的変数などが含まれ、オブジェクトはヒープに格納され、ローカルメソッドスタックは拡張ローカルメソッドです。仮想マシンstackはスタックフレームです。メソッドは、実行および生成されるスタックフレームです。実行後にリリースします。

2.仮想マシンスタック操作++ iおよびi ++

2.1仮想マシンスタックの内部を見てみましょう
ここに画像の説明を挿入
。2.11ローカル変数テーブル:主にパラメータデータ、ローカル変数データを格納します
。2.12オペランドスタック:LIFOのラストイン、ファーストアウトスタック。メソッドの実行中、さまざまなものがあります。バイトコード命令オペランドスタックは、データの書き込みまたは抽出、つまり、スタックおよびポップ操作です。
2.13動的接続:スタックフレームが定数プールに属するメソッドへの参照。この参照は、メソッド呼び出し中の動的接続をサポートするために使用されます。クラスファイルの定数プールには多数のシンボル参照があり、バイトコード命令は定数プールのシンボル参照をパラメーターとして受け取ります。シンボル参照は、静的分析と呼ばれる段階で使用されるときに直接参照に変換されます。
2.14リターンアドレス:終了するには、主に2つの方法があります。1つはバイトコード命令が通常プッシュされる方法、もう1つは異常な状況が異常な場合です。出口の種類に関係なく、前のメソッド呼び出しのPCカウンターの場所を知る必要があります。

3. ++ iとi ++は、ローカル変数テーブルとオペランドスタックを理解します

public static void main(String[] args) {
    
    
	a();
	b();
}

public static void a() {
    
    
	int i = 5;
	int j = i++;
	System.out.println(j);
}

public static void b() {
    
    
	int i = 6;
	int j = ++i;
	System.out.println(j);
}

-- 输出结果如下:
Connected to the target VM, address: '127.0.0.1:62076', transport: 'socket'
5
6
Disconnected from the target VM, address: '127.0.0.1:62076', transport: 'socket'

3.1バイトコード

 // access flags 0x9
 public static a()V
	L0
	 LINENUMBER 11 L0
	 // int类型5 压入栈
	 ICONST_5
	 // index为0 保存到局部变量表
	 ISTORE 0
	L1
	 LINENUMBER 12 L1
	 // index为0 从局部变量表压到栈
	 ILOAD 0
	 // 通过常量增加局部变量
	 IINC 0 1
	 // index为1 保存到局部变量表
	 ISTORE 1
	L2
	 LINENUMBER 13 L2
	 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
	 ILOAD 1
	 INVOKEVIRTUAL java/io/PrintStream.println (I)V
	L3
	 LINENUMBER 14 L3
	 RETURN
	L4
	 LOCALVARIABLE i I L1 L4 0
	 LOCALVARIABLE j I L2 L4 1
	 MAXSTACK = 2
	 MAXLOCALS = 2
 

 // access flags 0x9
 public static b()V
  L0
   LINENUMBER 17 L0
   // 将int型5 压入栈
   ICONST_5
   // index为0 保存至本地变量
   ISTORE 0
  L1
   LINENUMBER 18 L1
   // 通过常量增加局部变量
   IINC 0 1
   // 本地变量int型 index为0 读取到栈顶
   ILOAD 0
   // 将index为1 保存至本地变量
   ISTORE 1
  L2
   LINENUMBER 19 L2
   GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
   ILOAD 1
   INVOKEVIRTUAL java/io/PrintStream.println (I)V
  L3
   LINENUMBER 20 L3
   RETURN
  L4
   LOCALVARIABLE i I L1 L4 0
   LOCALVARIABLE j I L2 L4 1
   MAXSTACK = 2
   MAXLOCALS = 2

メソッドのバイトコードファイルを確認できます。L0操作は5をスタックに入れてから、ローカル変数テーブルに格納します
。L1操作は最初に0をILOADします(つまり、5をスタックjの値にロードします)。次にIINC0 1(Add one操作用)、最後にISTORE 1(iは6に割り当てられます)、つまり、jは最初にiの値を5として取得し、次に++操作を実行してiに割り当てます。実際、私はまだここで6歳です

bメソッドのバイトコードファイルであるL1操作は、IINC 0 1(最初にiに1を追加すると6)、次にILOAD 0(iの値は6がスタックにロードされる)、最後にISTORE 1(割り当てj)です。は6)つまり、高度な++操作を実行してからjを割り当てます。

4.クラスモデル

4.1 Klassモデル
ここに画像の説明を挿入
4.2通常のJavaクラスはJVMのinstanceKlassクラスに対応し、次の3つのワードクラスもあります
。4.21InstanceMirrorKlass:java.lang.Classを表すために使用され、Javaコードで取得されたClassオブジェクトです。実際にはこのC ++のインスタンスです。ヒープ領域に格納されているクラス、学名ミラークラス
4.22 InstanceRefKlass:java / lang / ref / Referenceクラスのサブクラスを表すために
使用されます4.23InstanceClassLoaderKlass:特定のローダーによってロードされたクラスをトラバースするために使用されます

4.3 Javaの配列は静的データ型ではなく、実行時に生成される動的データ型です。Java配列のメタ情報は、ArrayKlassのサブクラスで表され
ます。4.31TypeArrayKlass:基本型を表す
ために使用される配列4.32 ObjArrayKlass:使用される配列参照タイプの

  1. 定数プール
    5.1定数プールの最下層はStringTableであり、StringTableの最下層はHashTable HashTableです。Javaからのエントリであるソースコードユニットを確認できます。次に、コードに移動して、何が起こったかを確認します。メモリを選択し、このメモリを選択します。
    ここに画像の説明を挿入
public static void main(String[] args) {
    
    
    a();
    b();

}

public static void a() {
    
    
    String str = "11";
    String str1 = "11";
}

public static void b() {
    
    
    String str = new String("11");
    String str1 = new String("22");
}

1. String str = "11"; char [] + 1、j String +1
は、最初に定数プールに移動して定数11が見つからない場合はそれを見つけ、次にStringオブジェクトを作成してcharをロードします。文字列内の配列を押してからプッシュ定数プール定数プールに移動すると、11個のデータ
ここに画像の説明を挿入
2
を含むエントリが作成されます。2番目の文字列str1 = "11";このコード行は、最初に定数プールに移動して11を検索し、次にstr1はstr3が指すStringオブジェクトを指しています
ここに画像の説明を挿入
。Stringstr= new String( "11");
String +1しかないことがわかります。つまり、タイプ11のデータはすでに存在するため、新しいデータのみが存在します。が必要

ここに画像の説明を挿入
です。4。Stringstr1= new String( "22");
最初に定数プールに移動して11を見つけます。見つからない場合は、最初に "22"を実行します。これは、最初の例であるStringオブジェクトと同じ意味です。およびchar配列を作成し、新しいString()コンストラクターを実行してStringオブジェクトを作成します。

ここに画像の説明を挿入
概要:
String str = "11"であることがわかりました。
複数のStringオブジェクトが生成される場合、それは1つのStringオブジェクトです。
合計で複数のオブジェクトが生成される場合、2つのoopがあります(InstanceKlass TypeArrayKlass)

おすすめ

転載: blog.csdn.net/weixin_45657738/article/details/109474297