jvm内存模型

1、运行时数据区域java

1. 线程共享区并发

  方法区:用于存储被虚拟机加载的类信息常量静态变量等数据。jvm

  :用于存放对象实例(全部经过new建立的对象)xss

2. 线程独占区spa

  虚拟机栈:描述的是Java方法执行的内存模型。每一个方法在执行的同时都会建立一个栈帧,用于存储局部变量表操做数栈动态连接方法出口等信息。
  本地方法栈
:和虚拟机栈的做用相似,不一样点在于本地方法栈主要是为虚拟机使用到的Native方法提供服务。线程

  程序计数器:是一块较小的内存空间,是当前线程所执行的字节码的行号指示器。对象

3. 其它
  运行时常量池:方法区的一部分。用于存放编译期生成的各类字面量符号引用
  直接内存(堆外内存):不是jvm运行时数据区的一部分,也不是jvm规范中定义的内存区域。blog

2、内存划分内存

1. 堆:可经过 -Xmx -Xms 来分别设置最大堆内存初始时堆内存字符串

  new(新生代):用来存放jvm刚分配的java对象。可经过 -XX:MaxNewSize  -XX:NewSize 来分别设置最大内存初始时内存

    (a) eden:用来存放jvm刚分配的java对象。可经过 -XX:SurvivorRatio 来设置 eden 与1个 survivor 的比值(eden / survivor 的值)。

    (b) survivor1

    (c) survivor2

    PS:两个survivor空间同样大。eden中对象在gc后不会立马放入tenured区,会先放入survivor区中来回复制一段时间。

  tenured(老年代):用于存放新生代中通过屡次gc后仍然存活的对象。可经过 -XX:NewRatio 来设置老年代与新生代的比值(老年代 / 新生代的值)。

2. 方法区

  perm(永久代):可经过 -XX:PermSize -XX:MaxPermSize 来指定最小值和最大值。

  PS:perm区不等同于方法区,仅是Hotspot JVM 经过perm实现方法区。

     JDK1.7,已经把放在永久代的字符串常量池移到堆中。

     JDK1.8,撤销永久代,引入元空间。

3. 虚拟机栈:可经过 -xss 设置每一个线程的堆栈大小。

4. 本地方法栈

3、垃圾回收(gc)

1. 回收器 

  新生代gc:

    串行:可经过 -XX:+UseSerialGC 来强制指定。
    并行:可经过 -XX:+UseParallelGC 来强制指定,用 -XX:ParallelGCThreads 来指定线程数。
    并发:与老年代的并发gc配合使用。

  老年代gc:

    | 方式 | 新生代gc方式 | 老年代gc方式 |
    | :----: | :----: |:---: |
    | -XX:+UseSerialGC | 串行gc | 串行gc |
    | -XX:+UseParallelGC | 并行回收gc | 并行gc |
    | -XX:+UseConeMarkSweepGC | 并行gc | 并发gc |
    | -XX:+UseParNewGC | 并行gc | 串行gc |
    | -XX:+UseParallelOldGC | 并行回收gc | 并行gc |
    | -XX:+ UseConeMarkSweepGC、-XX:+UseParNewGC | 串行gc | 并发gc |

2. 什么时候回收

  (a) 新生代中eden区内存满时,引起普通gc。
  (b) 老年代满时,引起full gc。
  (c) 永久代满时,引起full gc。会致使class、method元信息的卸载。

3. 什么时候抛出`OutOfMemoryException`

  (a) jvm 98%的时间都花费在内存回收  (b) 每次回收的内存小于 2%