javaガベージ・コレクタとOutOfMemoryError

## ヒープ領域とは
JVMがプログラム実行時に確保するメモリ領域のうち、実行時に生成するオブジェクトのために割り当てられる領域をヒープ領域といいます。
## ガベージ・コレクタとは
ガベージ・コレクタ(GC)は、アプリケーションの動的メモリー割当てリクエストを自動的に管理します。
Java HotSpotガベージ・コレクションでは、様々な技術を採用して、これらの操作の効率性を改善します。
- 世代別のスカベンジをエージングとともに使用して、再利用可能で大きなメモリー領域が含まれている可能性のあるヒープ内の領域に集中します。
- 複数のスレッドを使用して、並列操作をアグレッシブに実行するか、アプリケーションと同時にバックグラウンドで長時間かかる操作を実行します。
- ライブ・オブジェクトを圧縮することで、連続的な大きな空きメモリーのリカバリを試行します。
## OutOfMemoryError
メモリー不足のためにJava Virtual Machineがオブジェクトを割り当てることができず、ガベージ・コレクタによっても使用可能なメモリーをこれ以上確保できない場合にスローされます。まるで抑制が無効になっているか、スタック・トレースへの書込みができないか、あるいはその両方であるかのように、仮想マシンによってOutOfMemoryErrorオブジェクトが構築される可能性があります。
## 実装確認
サンプルコード
```java
public class OOMTest {

  public static void main(String[] args) {
    int i=0;
    List<String> list = new ArrayList<>();
    String str = "OOM and GC";
    while(true) {
      list.add(str);
      str = str + str;
      i = i++;
    }
  }
}
```
実行オプション
```console
-Xms5m -Xmx5m -XX:+PrintGCDetails
```
実行結果
```console
[GC (Allocation Failure) [PSYoungGen: 1024K->505K(1536K)] 1024K->741K(5632K), 0.0028444 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1376K->500K(1536K)] 1612K->1139K(5632K), 0.0006508 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1320K->500K(1536K)] 1960K->1619K(5632K), 0.0007013 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1160K->500K(1536K)] 4200K->3876K(5632K), 0.0005479 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 500K->484K(1536K)] 3876K->3860K(5632K), 0.0003762 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 484K->0K(1536K)] [ParOldGen: 3375K->2714K(4096K)] 3860K->2714K(5632K), [Metaspace: 2683K->2683K(1056768K)], 0.0048137 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 20K->32K(1536K)] 4014K->4026K(5632K), 0.0003080 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 32K->0K(1536K)] [ParOldGen: 3994K->3354K(4096K)] 4026K->3354K(5632K), [Metaspace: 2683K->2683K(1056768K)], 0.0016179 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3354K->3354K(5632K), 0.0002432 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3354K->3342K(4096K)] 3354K->3342K(5632K), [Metaspace: 2683K->2683K(1056768K)], 0.0046264 secs] [Times: user=0.08 sys=0.00, real=0.00 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOfRange(Arrays.java:3664)
	at java.lang.String.<init>(String.java:207)
	at java.lang.StringBuilder.toString(StringBuilder.java:413)
Heap
 PSYoungGen      total 1536K, used 41K [0x00000000ffe00000, 0x0000000100000000, 0x0000000100000000)
  eden space 1024K, 4% used [0x00000000ffe00000,0x00000000ffe0a470,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 4096K, used 3342K [0x00000000ffa00000, 0x00000000ffe00000, 0x00000000ffe00000)
  object space 4096K, 81% used [0x00000000ffa00000,0x00000000ffd43840,0x00000000ffe00000)
 Metaspace       used 2717K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 287K, capacity 386K, committed 512K, reserved 1048576K
```
結果
PSYoungGen,ParOldGen,Metaspaceの世代別のスカベンジをエージングとともに使用しています。
OutOfMemoryErrorが発生する前に、Full GCが実行されています。