【Java開発】Javaのメモリ

#初めに

皆さん。こんにちは！

DreamHanksの254cmです。

今回は今までのjava記事で少しずつ言及されましたが

扱ってなかったメモリについて簡単に扱おうと思います。

Java記事のまとめは[こちら](https://qiita.com/DreamHanks/items/6b1996e1f8ed66bbd456)です。


##JVM

メモリについて話す前にJVMというものを分かる必要があります。

JVMは「**Java Virtual Machine**」の略であり、Javaプログラムを実際に実行するものです。

JVMはCPUやオペレーティングシステムに関係せず、Javaプログラムを実行することができます。

そのJVMの中にはClass Loader,Execution Engine, Garbage Collector, Runtime Data Areaなどで

構成されていますが、今回は「**Garbage Collector**」「**Runtime Data Area**」だけを扱います。

###Garbage Collector

Garbage CollectorはJVMのメモリ管理を担当するものです。

Garbage Collectorはオブジェクトの中でもう使わないオブジェクトのメモリを除去するものです。

###Runtime Data Area

Runtime Data AreaはJavaプログラムが実行するとき、実際のデータが格納される空間です。

この空間は大きくMethod領域、Heap領域、Stack領域、PC Resister領域、Native Method Stack領域で分かれています。

今回はMethod, Heap, Stack領域だけを扱います。

##Method領域

Method領域はクラスの情報が集まれています。

クラスのフィールド変数の名前、データ型、アクセス制御子情報のようなフィールド情報、

メソッドの名前、戻り値のデータ型、引数、アクセス制御子のようなメソッド情報、

static変数、final class変数などが格納されている領域です。

ここでstatic変数はJVMがJavaプログラムを実行するときにメモリを割り当てられ、

プログラムが終了される時にメモリが解除されます。

ですから、static変数はプログラムが実行される間に生成されているまま維持されるのでどこでも使えます。

##Heap領域

Heap領域も詳しく説明するといくつかの領域で別れていますが、今回は無視します。

Heap領域はnewで生成されたオブジェクトと配列のデータが格納される領域です。

**サンプル**

```java
public class ExampleCalss {
	public static void main(String[] args) {
		Human human = new Human();
	}
}

class Human {
	int age;
	String name;
}
```
クラスのフィールドの情報はMethod領域に格納されています。

newでクラスのコンストラクタを呼び出すとインスタンスが生成され、Heap領域に格納されます。

そのとき、各インスタンスのフィールドにメモリが割り当てられて値を代入したりすることができるようになります。

そしてHumanクラスの変数「**human**」はそのインスタンスのアドレスを保存します。
![20200929 Heap 영역 첨부자료1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/da523a1b-75a5-df3e-fbc1-00826084aae5.png)

###Heap領域でGarbage Collectorの役割

Garbage Collectorは誰も参照しないメモリ空間を対象にして削除します。

**サンプル**

```java
public class ExampleCalss {
	public static void main(String[] args) {![20200929 Heap 영역 첨부자료2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/f85e9c28-dbe5-db5d-edd1-6a75a4b54065.png)

		Human human = new Human();
		human = null;
		human = new Human();
	}
}

class Human {
	int age;
	String name;
}
```
上記のサンプルを見るとhumanが指しているメモリのアドレスをnullにしています。

そしてhumanに新しいインスタンスを生成して参照させています。

つまり、一つ目に割り当てられたインスタンスは誰も参照していないです。

そういうメモリ空間(一つ目のインスタンス)がGarbage Collectionの対象になります。

※Garbage CollectionはGarbage Collectorが誰も参照しないメモリを消す動作を意味します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/04d20dda-00e6-263c-dfef-bec8dc03491d.png)

##Stack領域

ローカル変数、引数、戻り値とかのデータが格納される領域です。

Stack領域には基本型の変数は変数とそのデータが一緒に格納されますが、

参照型(オブジェクト)はインスタンスのアドレスだけを格納して、実際のデータはHeap領域に格納されます。

Stack領域はメソッドを呼び出すたび、個物的に生成されます。



**サンプル**

```java
public class ExampleCalss {
	public static void main(String[] args) {
		int age = 10;
		age = mutiply(age, 4);
	}
	
	static int mutiply(int num1, int num2) {
		int result = num1*num2;
		return result;
	}
}
```

上記の場合を順に説明すると(argsは無視します。)

① mainメソッドのStack領域が生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/0dfaebb8-9cdc-b2d0-cad3-fc9d088fbc5b.png)


②　ageが生成され、10で初期化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/c273af19-911a-2316-fdf7-589a9d448210.png)

③ multiplyメソッドが実行され、Stack領域が生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/a398b670-f056-2a17-32dd-c73948c395cd.png)

④ multiplyの引数が生成され、渡された値で初期化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/97d31caf-a8dd-8754-4072-5ed036951b4f.png)

⑤ valueが生成され、演算の結果が代入されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/43283de9-fac2-0e47-d6ef-34aecd11efa3.png)

⑥ returnが実行され、mutiplyの実行が終了されます。そしてmultiplyで使われた変数はStackで削除されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/e95edddf-2523-c17b-229f-460e77e30ec3.png)

⑦ multiplyメソッドの実行結果がageに代入されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/a126cf35-81d8-7845-6fd1-1a3ec5175d52.png)

⑧ mainメソッドが終了され、mainメソッドで使われた変数が削除されます。

#終わりに

今回の記事は以上になります。

ご覧いただきありがとうございます。

以後の記事はDreamHanksのブログで連載されます。

私たちの最新の記事は[こちら](http://blog.dreamhanks.com/java%e5%85%a5%e9%96%80%e8%ac%9b%e5%ba%a7/)で確認できます。