diff --git a/notes/JVM.md b/notes/JVM.md
index e3935bee..0605479c 100644
--- a/notes/JVM.md
+++ b/notes/JVM.md
@@ -1,101 +1,164 @@
-[TOC]
+
+* [内存模型](#内存模型)
+ * [1. 程序计数器](#1-程序计数器)
+ * [2. Java 虚拟机栈](#2-java-虚拟机栈)
+ * [3. 本地方法栈](#3-本地方法栈)
+ * [4. Java 堆](#4-java-堆)
+ * [5. 方法区](#5-方法区)
+ * [6. 运行时常量池](#6-运行时常量池)
+ * [7. 直接内存](#7-直接内存)
+* [垃圾收集](#垃圾收集)
+ * [1. 判断一个对象是否可回收](#1-判断一个对象是否可回收)
+ * [1.1 引用计数](#11-引用计数)
+ * [1.2 可达性](#12-可达性)
+ * [1.3 引用类型](#13-引用类型)
+ * [1.3.1 强引用](#131-强引用)
+ * [1.3.2 软引用](#132-软引用)
+ * [1.3.3 弱引用](#133-弱引用)
+ * [1.3.4 虚引用](#134-虚引用)
+ * [1.3 方法区的回收](#13-方法区的回收)
+ * [1.4 finalize()](#14-finalize)
+ * [2. 垃圾收集算法](#2-垃圾收集算法)
+ * [2.1 标记-清除算法](#21-标记-清除算法)
+ * [2.2 复制算法](#22-复制算法)
+ * [2.3 标记-整理算法](#23-标记-整理算法)
+ * [2.4 分代收集算法](#24-分代收集算法)
+ * [3. 垃圾收集器](#3-垃圾收集器)
+ * [3.1 Serial 收集器](#31-serial-收集器)
+ * [3.2 ParNew 收集器](#32-parnew-收集器)
+ * [3.3 Parallel Scavenge 收集器](#33-parallel-scavenge-收集器)
+ * [3.4 Serial Old 收集器](#34-serial-old-收集器)
+ * [3.5 Parallel Old 收集器](#35-parallel-old-收集器)
+ * [3.6 CMS 收集器](#36-cms-收集器)
+ * [3.7 G1 收集器](#37-g1-收集器)
+ * [3.8 七种垃圾收集器的比较](#38-七种垃圾收集器的比较)
+ * [4. 内存分配与回收策略](#4-内存分配与回收策略)
+ * [4.1 优先在 Eden 分配](#41-优先在-eden-分配)
+ * [4.2 大对象直接进入老年代](#42-大对象直接进入老年代)
+ * [4.3 长期存活的对象进入老年代](#43-长期存活的对象进入老年代)
+ * [4.4 动态对象年龄判定](#44-动态对象年龄判定)
+ * [4.5 空间分配担保](#45-空间分配担保)
+ * [5. Full GC 的触发条件](#5-full-gc-的触发条件)
+ * [5.1 调用 System.gc()](#51-调用-systemgc)
+ * [5.2 老年代空间不足](#52-老年代空间不足)
+ * [5.3 空间分配担保失败](#53-空间分配担保失败)
+ * [5.4 JDK 1.7 及以前的永久代空间不足](#54-jdk-17-及以前的永久代空间不足)
+ * [5.5 Concurrent Mode Failure](#55-concurrent-mode-failure)
+* [类加载机制](#类加载机制)
+ * [1 类的生命周期](#1-类的生命周期)
+ * [2. 类初始化时机](#2-类初始化时机)
+ * [3. 类加载过程](#3-类加载过程)
+ * [3.1 加载](#31-加载)
+ * [3.2 验证](#32-验证)
+ * [3.3 准备](#33-准备)
+ * [3.4 解析](#34-解析)
+ * [3.5 初始化](#35-初始化)
+ * [4. 类加载器](#4-类加载器)
+ * [4.1 类与类加载器](#41-类与类加载器)
+ * [4.2 类加载器分类](#42-类加载器分类)
+ * [4.3 双亲委派模型](#43-双亲委派模型)
+* [JVM 参数](#jvm-参数)
+ * [GC 优化配置](#gc-优化配置)
+ * [GC 类型设置](#gc-类型设置)
+
-# 内存模型
-
+# 内存模型
+
+
注:白色区域为线程私有的,蓝色区域为线程共享的。
-## 1. 程序计数器
+## 1. 程序计数器
-记录正在执行的虚拟机字节码指令的地址(如果正在执行的是 Native 方法则为空)。
+记录正在执行的虚拟机字节码指令的地址(如果正在执行的是 Native 方法则为空)。
-## 2. Java 虚拟机栈
+## 2. Java 虚拟机栈
-每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
+每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
该区域可能抛出以下异常:
-1. 当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常;
-2. 栈进行动态扩展时如果无法申请到足够内存,会抛出 OutOfMemoryError 异常。
+1. 当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常;
+2. 栈进行动态扩展时如果无法申请到足够内存,会抛出 OutOfMemoryError 异常。
-## 3. 本地方法栈
+## 3. 本地方法栈
-与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法服务。
+与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法服务。
-## 4. Java 堆
+## 4. Java 堆
所有对象实例都在这里分配内存。
-这块区域是垃圾收集器管理的主要区域("GC 堆 ")。现在收集器基本都是采用分代收集算法,Java 堆还可以分成:新生代和老年代(新生代还可以分成 Eden 空间、From Survivor 空间、To Survivor 空间等)。
+这块区域是垃圾收集器管理的主要区域("GC 堆 ")。现在收集器基本都是采用分代收集算法,Java 堆还可以分成:新生代和老年代(新生代还可以分成 Eden 空间、From Survivor 空间、To Survivor 空间等)。
-不需要连续内存,可以通过 -Xmx 和 -Xms 来控制动态扩展内存大小,如果动态扩展失败会抛出 OutOfMemoryError 异常。
+不需要连续内存,可以通过 -Xmx 和 -Xms 来控制动态扩展内存大小,如果动态扩展失败会抛出 OutOfMemoryError 异常。
-## 5. 方法区
+## 5. 方法区
用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
-和 Java 堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出 OutOfMemoryError 异常。
+和 Java 堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出 OutOfMemoryError 异常。
-对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现,HotSpot 虚拟机把它当成永久代来进行垃圾回收。
+对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现,HotSpot 虚拟机把它当成永久代来进行垃圾回收。
-## 6. 运行时常量池
+## 6. 运行时常量池
运行时常量池是方法区的一部分。
-类加载后,Class 文件中的常量池(用于存放编译期生成的各种字面量和符号引用)就会被放到这个区域。
+类加载后,Class 文件中的常量池(用于存放编译期生成的各种字面量和符号引用)就会被放到这个区域。
-在运行期间也可以用过 String 类的 intern() 方法将新的常量放入该区域。
+在运行期间也可以用过 String 类的 intern() 方法将新的常量放入该区域。
-## 7. 直接内存
+## 7. 直接内存
-在 JDK 1.4 中新加入了 NIO 类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
+在 JDK 1.4 中新加入了 NIO 类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
-# 垃圾收集
+# 垃圾收集
-程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收。垃圾回收主要是针对 Java 堆和方法区进行。
+程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收。垃圾回收主要是针对 Java 堆和方法区进行。
-## 1. 判断一个对象是否可回收
+## 1. 判断一个对象是否可回收
-### 1.1 引用计数
+### 1.1 引用计数
-给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。
+给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。
-两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致 GC 收集器无法回收。
+两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致 GC 收集器无法回收。
```java
-objA.instance = objB;
-objB.instance = objA;
+objA.instance = objB;
+objB.instance = objA;
```
-### 1.2 可达性
+### 1.2 可达性
-通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是都是可用的,不可达的对象可被回收。
+通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是都是可用的,不可达的对象可被回收。
-GC Roots 一般包含以下内容:
+GC Roots 一般包含以下内容:
-1. 虚拟机栈中引用的对象
-2. 方法区中类静态属性引用的对象
-3. 方法区中的常量引用的对象
-4. 本地方法栈中引用的对象
+1. 虚拟机栈中引用的对象
+2. 方法区中类静态属性引用的对象
+3. 方法区中的常量引用的对象
+4. 本地方法栈中引用的对象
-### 1.3 引用类型
+### 1.3 引用类型
无论是通过引用计算算法判断对象的引用数量,还是通过可达性分析算法判断对象的引用链是否可达,判定对象是否存活都与“引用”有关。
-Java 对引用的概念进行了扩充,引入四种强度不同的引用类型。
+Java 对引用的概念进行了扩充,引入四种强度不同的引用类型。
-#### 1.3.1 强引用
+#### 1.3.1 强引用
只要强引用存在,垃圾回收器永远不会回收调掉被引用的对象。
-使用 new 一个新对象的方式来创建强引用。
+使用 new 一个新对象的方式来创建强引用。
```java
-Object obj = new Object();
+Object obj = new Object();
```
-#### 1.3.2 软引用
+#### 1.3.2 软引用
用来描述一些还有用但是并非必需的对象。
@@ -103,36 +166,36 @@ Object obj = new Object();
软引用主要用来实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源获取数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源获取这些数据。
-使用 SoftReference 类来实现软引用。
+使用 SoftReference 类来实现软引用。
```java
-Object obj = new Object();
-WeakReference