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%