Javaオブジェクトメモリ管理スタックとメソッド領域の分析

非ヒープスタック

Javaオブジェクトメモリ管理ヒープの分析

前の章にジャンプするには、このリンクを開いてください:https
//blog.csdn.net/QQ1043051018/article/details/112341273

スタックは、ローカル変数をメソッドに格納するための専用です

スタックスペースは、プログラムの実行時にプログラムとメソッドで宣言されたすべてのローカル変数を格納するために使用されます。
ローカル変数:メソッドで宣言された変数です。
パラメーター変数、メソッド本体で宣言された変数、コードセグメント内の中括弧で宣言された変数が含まれます。
メンバー変数はスタックに格納され、ライフサイクルはメソッドのライフサイクルと同じです。

例:ご飯の炊き方を確認します。mainメソッドで呼び出された場合はどうなりますか?

package day05;

public class buy {
    
    
    public static void main(String[] args) {
    
    
          /*栈测试*/
        double card=10; //饭卡里有10块钱
        char lp = buy('鱼',card);
        System.out.println("card的余额: "+card); // 7
    }

    /**
     * 帮同学打饭
     * @param what  菜名
     * @param card  饭卡余额
     * @return 打到的菜名
     */
    public static char buy(char what, double card) {
    
    
        card -=3; //每次减3元
        System.out.println("余额"+card); //10
        return what;
    }
}

出力結果:
ローカル変数スコープ:定義された中括弧にのみ限定され、この中括弧のサブ括弧は有効です。
ここに画像の説明を挿入

ローカル変数のライフサイクル

Javaプログラムでメソッドが呼び出されるたびに、JVMはスタック内の現在のメソッドに必要なスペースを割り当てます。このスペースはメソッドの「スタックフレーム」と呼ばれます。スタックフレームは、特に呼び出されるメソッドに対応します。メソッドのパラメーターやローカル変数などのデータ変数は、スタックフレームに格納されます。メソッド呼び出しが完了すると、メソッドのスタックフレームがクリアされ、同時にローカル変数が無効になります。

シミュレーションを開始しましょう。
最初に、プログラムは最初にmainメソッドを実行し、mainメソッド用に2つのスタックフレームを作成します。
ここに画像の説明を挿入
次に、割り当て
ここに画像の説明を挿入
購入の実装は
ここに画像の説明を挿入、呼び出しが完了したときにメソッドの後にメソッドを呼び出し続け、スタックフレームメソッドがクリアされます。
ここに画像の説明を挿入

メンバー変数とローカル変数

メンバー変数とローカル変数の違いは次のとおりです。

ローカル変数:

-範囲:定義された中括弧にのみ限定され、この中括弧の括弧内で有効です。
-保存場所:スタック(
zhan )メモリに保存-メソッドまたはステートメントブロックで定義;-
デフォルト値なし、自分で初期値を設定する必要があります;
-メソッドが呼び出されると、スタックに保存され、メソッド呼び出しは、スタックから終了します。途中でクリアします
。-ライフサイクル:ブラケットの終わりで消えます。

メンバー変数:

-メソッド外のクラスで定義されています
。-明示的に初期化できないデフォルトの初期値があります。-
クラスがインスタンス化された後、ヒープに格納され、オブジェクトがリサイクルされると、メンバー変数は次のようになります。無効;

メンバー変数、ローカル変数、静的変数の違い

ここに画像の説明を挿入

学生の料理を支援するケーススタディ:

まず、ミールカード情報をカプセル化するクラスを作成します

/**
 * 封装饭卡信息的类
 */
public class Card {
    
    
    //创建2个成员变量
    String name;//饭卡的主人
    double bal; //饭卡的余额

    /**
     * 初始化所有成员变量的构造方法
     * @param name 饭卡的主人
     * @param bal  饭卡的余额
     */
    public Card(String name, double bal) {
    
    
        this.name = name;
        this.bal = bal;
    }
}

学生が食事を準備するのを助けるためにテストを実行し、食事カードの残高が3元減少するかどうか

public class buy {
    
    
    public static void main(String[] args) {
    
    
       /*栈测试*/
      //创建一个饭卡对象lpCard,封装饭卡的余额
      //把lpCard对象封装到Card类中
      Card lpCard=new Card("LP",10);
      //lpCard去打饭,鱼
      char lp=buy('鱼',lpCard);
      //打印饭卡的余额
        System.out.println("饭卡的余额"+lpCard.bal);
    }

    /**
     * 这个方法是 使用Card类型对象作为参数的buy方法
     * @param what
     * @param card
     * @return
     */
    public static char buy(char what,Card card){
    
    
        //从饭卡对象的bal属性中减3元
        card.bal-=3;
        //打印饭卡对象的余额属性
        System.out.println("余额: "+card.bal);
        return what; //返回打到的菜名

    }
    /**
     * 帮同学打饭
     * @param what  菜名
     * @param card  饭卡余额
     * @return 打到的菜名
     */
    public static char buy(char what, double card) {
    
    
        card -=3; //每次减3元
        System.out.println("余额"+card);
        return what; //返回打到的菜名
    }
}

ここに画像の説明を挿入

次に、写真を使用して動作原理を見てみましょう。

最初に、プログラムはmainメソッドを実行して、スタック内にスタックフレームを作成します。スタックフレームに
ここに画像の説明を挿入
は、2つのローカル変数lpCardとlpが含まれ
、最初の文が実行されます。CardlpCard = new Card( "LP"、10);

newがヒープに表示される場合、それはCardタイプオブジェクトのストレージスペースをヒープ内に作成する必要があることを意味します
。Cardにはnameとbalの2つのメンバー変数が含まれます。new
はパラメーター化された構造を同時に呼び出すため、デフォルトで初期化されるため、これら2つのメンバー変数には初期値があります。

ここに画像の説明を挿入
次に、buyメソッドを呼び出してパラメータを渡します
。buyメソッドが呼び出されると、stackメソッドのスタックフレームがスタックで開かれ、buyのパラメータとローカル変数が保存されます
ここに画像の説明を挿入
。buyメソッドが呼び出されると、lpCardのアドレス値が渡されます。

ここに画像の説明を挿入結果は次のパターンになり
ます。card変数とlpCaed変数は、ヒープ内の同じミールカードオブジェクトを同時に指します。
このとき、どちらのパーティがミールカードオブジェクトを変更しても、同じオブジェクトを直接変更し、もちろんお互いに影響し合います。
ここに画像の説明を挿入次に、buyメソッドの呼び出しが終了しても、未使用のメソッドフレームは存在しませんが、スタック上のオブジェクトは存在します。
スタック内のオブジェクトを再利用できるのはgcのみであるため、いつ再利用されるかは不明です。その上、lpCardはまだ呼び出しています。

ここに画像の説明を挿入


総括する:

ライフケース:スタックは実際にはレストランの座席のようなものです。スタックに人が来ると、離れると解放されます。

スタックについて多くを語った後、メソッド領域を調べます

非ヒープ方式の領域

メソッド領域とは何ですか?

メソッド領域は、クラス情報を格納するために使用されます。
注:オブジェクト情報ではなく、クラス情報を格納します。クラスはオブジェクトのテンプレートです。オブジェクトは、実際にはクラスの説明に従って作成されます。
オブジェクトはヒープ内にあり、クラス情報はメソッド領域にあります

Javaプログラムの実行中は、クラスファイルのバイトコード情報(つまり、.classのコンテンツ)が最初にクラスローダーを介してロードされ、解析後にクラス情報がメソッド領域にロードされます。
クラス情報には、メンバー変数とメソッド定義が含まれます。

ここに画像の説明を挿入

例えとしてライフケースを取り上げましょう。

実は、この方法や情報は、レストランの特製料理のポスターのようなものです。レストランの壁には、説明付きの特製料理のポスターがたくさん貼られています。基本的なシェフがこの料理を作るときは、壁の写真に従います。 。注文したい場合は、壁の写真を参照することもできます。

注:通常、メソッド領域のクラス情報は、最初のインスタンス化の前に1回だけロードされます。頻繁にリロードしないでください。

それはレストランに掲示される特製料理のようなもので、通常は同じです。

実際、mainメソッドはプログラムの最初に呼び出す必要があるため、最初に、テスト情報全体がメソッド領域にロードされます。
次に、次のメソッド領域で、テストクラスのshowMem()の説明を段階的に実行できます。
ここに画像の説明を挿入
showMem()は、実行プロセス中に2回呼び出されますが、どこで何度呼び出されてもかまいません。
TestでのshowMem()メソッドの定義は、メソッド領域にのみ格納されます。

まるで実際のように、壁には常に特製料理が1つしかなく、シェフはこの写真の見た目と練習に従って、多くの顧客のために複数の料理を繰り返し調理します。
そのため、レシピは1つだけで、シェフがレシピに従って繰り返し実行します。
ここに画像の説明を挿入

最後に、メソッド領域のクラス情報のライフサイクル。基本的に、ほとんどのクラス情報は、インスタンス化されたオブジェクトを初めて使用する前に1回だけロードされ、メソッド領域に保持されます。

最後に、概要を覚えておいてください。

2つの部屋と1つのホール:

ここに画像の説明を挿入

最大かつ最も柔軟なのはヒープであり、次にスタックが続きます。スタックはプログラムの実行中に絶えず変化し、最後にメソッド領域は比較的固定されています。



過去の知識のJavaオブジェクトメモリ管理ヒープの分析

勉強しなかった、またはもっと知りたい場合は、このリンクを開いて前の章にジャンプしてくださいhttps
//blog.csdn.net/QQ1043051018/article/details/112341273

おすすめ

転載: blog.csdn.net/QQ1043051018/article/details/112384674