JVMシリーズのメモリモデルを詳しく説明します。


1.メモリモデルと運転時データエリア
この章はJava仮想マシンのメモリモデルを勉強しています。jvm運行時のデータベースは規範ですが、JVMメモリモデルは仕様変更の実現に対してです。

java仮想マシンはデータを重点的に記憶するのがヒープと方法エリアですので、この章もこの二つの方面から比較的に詳しく説明します。ヒープと方法エリアはメモリ共有であり、java仮想マシンスタック、Native方法スタック、プログラムカウンタはスレッドプライベートである。

2、思考図と凡例

一つは非ヒープゾーンで、方法エリアも一般的に「永久代」と呼ばれています。もう一つはヒープエリアで、young区とold区に分けられています。young区はまた二つの部分に分けられています。一つはEden区で、一つはSurvivor区(S 0+S 1)で、S 0区はFrom区とも言えます。S 1はTo区とも言えます。

3、対象はJVMに空間を申請する

4、なぜSurvivorエリアが必要ですか?
なぜSurvivorエリアが必要ですか?Edenだけではだめですか?
Survivorエリアを設計しないと、EdenエリアはMinorGCを行い、対象はそのままOldエリアに送られます。そうすると、Oldエリアはすぐに満たされます。Oldエリアが満杯になると、FulGC(OldエリアはMajorGCを行います。MinorGCに伴います)が行われ、FulGCは時間がかかります。
補足:Minor GC:新生代
Major GC:古い時代
Full GC:新生代+古い時代
Eden:S 1:S 2は8:1:1です
5、なぜ二つのSurvivorエリアが必要ですか?
二つのSurvivorエリアが必要なのはメモリの断片化を避けるためです。なぜですか?
Survivorエリアは一つしか設計されていないと仮定して、Edenエリアが満杯になるとMinor GC、Edenエリアで生存しているオブジェクトはSurvivorエリアに移動され、次のEdenエリアが満期になると問題が発生します。MinorGCを行うとEdenエリアのオブジェクトをSurvivorエリアにハードに配置します。
6、例を検証する
メモリオーバーフロー

import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class HeapController {

    List<Foo> list = new ArrayList<Foo>();
    @GetMapping(value = {"heap"})
    public String heapTest() {
        while (true) {
            list.add(new Foo());
        }
    }


    @Data
    class Foo {
        String str;
    }
}
メモリオーバーフローが発生しました。
java.lang.OutOfMemoryError:Java heap space

パラメータの設定ができます。たとえば-Xms 64 M-Xmx 512 M
メソッドエリアメモリオーバーフロー
asmを使用して、mavenの配置:

<dependency>
  <groupId>asm</groupId>
  <artifactId>asm</artifactId>
  <version>3.3.1</version>
</dependency>
コードを編纂して、方法区の中にクラスの情報を添加して、注意して、コンピュータの性能はあまり良くなくて、このコードを実行しないでください、容易で、コンピュータの再起動をもたらして、あまりにメモリを食べて、小さい循環の回数をも調節することができます。

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.util.ArrayList;
import java.util.List;

public class MyMetaspace extends ClassLoader {

  public static List<Class<?>> createClasses() {
    List<Class<?>> classes = new ArrayList<Class<?>>();
    for (int i = 0; i < 10000000; ++i) {
      ClassWriter cw = new ClassWriter(0);
      cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,
              "java/lang/Object", null);
      MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
              "()V", null, null);
      mw.visitVarInsn(Opcodes.ALOAD, 0);
      mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
              "<init>", "()V");
      mw.visitInsn(Opcodes.RETURN);
      mw.visitMaxs(1, 1);
      mw.visitEnd();
      MyMetaspace test = new MyMetaspace();
      byte[] code = cw.toByteArray();
      Class<?> exampleClass = test.defineClass("Class" + i, code, 0,
              code.length);
      classes.add(exampleClass);
    }
    return classes;
  }
}
方法ゾーンテストインターフェース:

import com.example.jvm.jvmexceptionexample.asm.MyMetaspace;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class NonHeapController {

    List<Class<?>> list = new ArrayList<Class<?>>();

    @GetMapping(value = {"/noheap"})
    public String noheap() {
        while (true) {
            list.addAll(MyMetaspace.createClasses());
        }
    }

}
java.lang.OutOfMemoryError:Metaspace
at java.lag.lassLoader.defineClass 1(Native Method)~[na:1.8.5_]54)
処理方法は、メタスペースのサイズを設定します。例えば、-XX:Metaspace Size=64 M-XX:MaxMetaspace Size=512 M
Java仮想マシンスタック
前の学習では、Java仮想マシンスタックは、スタックフレームによって格納され、一つの方法は、スタックフレームに対応し、キューモードでスタックに進むので、テストプログラムによってJava仮想マシンスタックに問題が発生し、再帰的な方法でテストすることができる。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StackController {

    public static long count = 0;

    public static void add(long i) {
        count ++ ;
        add(i);
    }

    @GetMapping(value = {"stack"})
    public void stack() {
        add(1);
    }

}
StockOverflow、スタックオーバーフロー異常:
java.lang.Stock OverflowError:null
at comple.example.jvmexceptionexample.com.StocController.add(StocController.java:14)~[clases/na]
処理方法は、-Xss 256 kを設定します。各スレッドのスタックサイズを設定します。JDK 5以降は各スレッドスタックのサイズは1 Mで、以前は各スレッドスタックのサイズは256 Kであった。
以上はJVMシリーズのメモリモデルの詳細内容を詳しく説明しました。JVMメモリモデルのメモリ構造に関する資料は他の関連記事に注目してください。