Javaは、メモリをスタックメモリとヒープメモリの2つのタイプに分けます。ヒープとスタックの両方がJavaによってRamにデータを格納するために使用されます。
1.はじめに:
アプリケーションのすべての部分がヒープメモリを使用し、スタックメモリがスレッドを通過します。
Javaの関数呼び出しでパラメーターを渡すときは、値転送の原則に従います。
したがって、基本型はデータ値自体を転送します(例:a = 1、b = a、b = 1 + 2の場合、b = 3 、aはまだ1)
参照タイプの転送はオブジェクトの参照です。つまり、リンクリストのアドレスが渡されます(例:objectA = tomato、B = objectA、ただしAのメモリアドレスはBに与えられます)
1.スタックメモリは
関数内にありますいくつかの定義された基本型変数とオブジェクト参照変数は、関数のスタックメモリに割り当てられます。
2.ヒープメモリ
(1)ヒープを使用すると、プログラムは実行時に特定のサイズのメモリスペースに動的に適用できます。ヒープメモリは、実際には、ヒープメモリの性質を満たす優先度付きキューのデータ構造です。
(2)ヒープメモリはメモリスペースに動的に適用されます:
まず、オペレーティングシステムに空きメモリアドレスを記録するリンクリストがあることを確認します。
次に、システムがプログラムリクエストを受信すると、リンクリストをトラバースして、最初のヒープノードを見つけます。スペースが
再び要求されたスペースよりも大きくなります。見つかったヒープノードが空きノードリストから削除され、ノードのスペースがプログラムに割り当てられます。
ps:後でスペースを解放しやすくするために、この割り当てのサイズは、割り当てられたスペースの最初のアドレスに記録されます。
ps:見つかったスペース>申請されたスペースの場合、システムは余分なスペースをスペースリンクリストに自動的に再配置します。
次に、ヒープメモリとスタックメモリの比較
スタックメモリ | ヒープメモリ | |
---|---|---|
保存されたコンテンツ | 一時変数、ローカル変数(基本型変数、オブジェクト参照)、メソッド呼び出し | すべての新しいオブジェクト(つまり、インスタンス変数)と配列を格納します。割り当て方法は、リンクリストに似ています。 |
出入りの原則 | 先入れ先出し(バケットと同様) | 上位アドレスに拡張されたデータ構造は不連続なメモリ空間であり、リンクリストのトラバース方向は下位アドレスから上位アドレスへです。 |
例えば | たとえば、test0関数はmain関数で呼び出され、test0が最初に解放され、次にmainが解放されます。 | -------- |
リサイクルメカニズム | 変数のスコープを超えると、スタックメモリスペースが自動的に解放されます | ガベージコレクターは、使用されなくなったデータを自動的に収集します |
使用範囲 | スタックメモリは他のスレッドからアクセスできません | ヒープメモリ内のフォーメーションはグローバルにアクセス可能です |
メモリオーバーフロー | スタックメモリがいっぱいになると、java.lang.StackOverFlowError例外をスローします | ヒープメモリがいっぱいになると、java.lang.OutOfMemoryErrorをスローします:JavaHeapSpaceエラー |
長所と短所 | 小さなスタックメモリ | ヒープメモリ取得スペースはより柔軟で、比較的大きい() |
短いライフサイクル | プログラム実行の開始から実行の終了までのヒープメモリ | |
速いアクセス速度 | アクセス速度が遅い(メモリの断片化が発生しやすいが、使いやすい) | |
スタックデータは共有できますが、スタックに格納されるデータのサイズと存続期間は随時決定する必要があり、柔軟性に欠けます。 | – |
3.メモリ解析例
(1)コードの実装
この例は、3次元空間で点を定義し、座標の変更と点と原点との距離を実現するクラスです。
この例を書くアイデア:
1)分析される属性は次のとおりです:ポイント、3つの座標(x、y、z)
メソッド:ポイントの初期化(構築方法)、座標の変更(セット)、座標値の取得(取得) 、
達成する距離2)の二乗の合計を求めます。具体的なコードは次のとおりです。
package OOP;
class Point {
private double coordinateX ;
private double coordinateY ;
private double coordinateZ ;
Point(double x,double y,double z){
coordinateX = x;
coordinateY = y;
coordinateZ = z;
}
public void setCoordinateX(double coordinateX) {
this.coordinateX = coordinateX;
}
public double getCoordinateX() {
return coordinateX;
}
public void setCoordinateY(double coordinateY) {
this.coordinateY = coordinateY;
}
public double getCoordinateY() {
return coordinateY;
}
public void setCoordinateZ(double coordinateZ) {
this.coordinateZ = coordinateZ;
}
public double getCoordinateZ() {
return coordinateZ;
}
//计算点到原点的距离的平方
public double distanceSquare(){
double disSquare = coordinateX*coordinateX +coordinateY*coordinateY +coordinateZ*coordinateZ;
return disSquare;
}
}
public class TestPoint{
public static void main(String args[]){
//生成特定坐标的点对象
Point p1 = new Point(1,2,3);
System.out.println("生成的点是"+"("+p1.getCoordinateX() + ","+p1.getCoordinateY()+ ","+p1.getCoordinateZ() +")");
//设置坐标
p1.setCoordinateX(6);
System.out.println("p1的x轴应该是6 "+p1.getCoordinateX());
//计算点到原点的平方
double dis1 = p1.distanceSquare();
System.out.println(dis1);
}
2.メモリ分析
(1)最初のステップは
、p1参照オブジェクトを定義し、スタックメモリにスペース1b6d3586を割り当て、スタックメモリにスペースを適用することです。
新しいポイント(1、2、3)を実行します。xを割り当てます。 、スタックメモリ内のy、Zはそれぞれ1、2、3です
。coordinateX= x値1、coordinateY = y値2、coordinateZ = z値3、
構築ポイントが完了すると、x、y、zスタックメモリが解放されます
(2)2番目のステップはgetCoordinateX()
p1.getCoordinateX()を呼び出すことで、値が読み取られ、メモリは変更されません
(3) 3番目のステップ:setCoordinateX(6)を呼び出します
1)パス入力パラメーター6、最初にスタックメモリにスペースを追加して、渡されたパラメーター6を格納します
:2)は、以下の方法を実行し
ます。public void setCoordinateX(ダブルcoordinateX){ ; this.coordinateX = coordinateX } (これは、Javaコールの値転送の原理を反映する)新たに渡さ6にP1のT書き換えcoordinateXを。このとき、のメモリ:
3)メソッドの実行後、6のストレージスペースがスタックメモリに解放されます。4。4番目のステップは
座標を読み取ることであり、メモリは変更されません。5.5
番目のステップは距離を計算することです
doubledis1 = p1.distanceSquare();
スタックメモリにdis1を追加し、計算結果をdis1に格納します。
6.ステップ6:プログラムの実行後、すべてのメモリを解放します
。System.out.println(dis1);の場合、最後の文が実行された後、スタックメモリはdis1、p1を解放し、
ヒープコレクタは未使用のヒープをガベージします。メモリデータのリサイクル。
この時点で、メモリは以前と同じように復元され、空になっています。。。ハハ、何
が悪いのか、アドバイスしてください。