diff --git a/docs/java/basis/java-basic-questions-01.md b/docs/java/basis/java-basic-questions-01.md index 820e6e92..6e7c23b4 100644 --- a/docs/java/basis/java-basic-questions-01.md +++ b/docs/java/basis/java-basic-questions-01.md @@ -34,7 +34,7 @@ Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不 除了我们平时最常用的 HotSpot VM 外,还有 J9 VM、Zing VM、JRockit VM 等 JVM 。维基百科上就有常见 JVM 的对比:[Comparison of Java virtual machines](https://en.wikipedia.org/wiki/Comparison_of_Java_virtual_machines) ,感兴趣的可以去看看。并且,你可以在 [Java SE Specifications](https://docs.oracle.com/javase/specs/index.html) 上找到各个版本的 JDK 对应的 JVM 规范。 -![Java SE Specifications](/Users/guide/Documents/GitHub/JavaGuide/docs/java/basis/images/java-se-specifications.png) +![Java SE Specifications](./images/java-se-specifications.png) #### JDK 和 JRE diff --git a/docs/java/jvm/jvm-garbage-collection.md b/docs/java/jvm/jvm-garbage-collection.md index 11c99494..432daa4a 100644 --- a/docs/java/jvm/jvm-garbage-collection.md +++ b/docs/java/jvm/jvm-garbage-collection.md @@ -1,11 +1,10 @@ --- +title: JVM 垃圾回收详解 category: Java tag: - JVM --- -# JVM 垃圾回收详解 - ## 写在前面 ### 本节常见面试题 diff --git a/docs/java/jvm/memory-area.md b/docs/java/jvm/memory-area.md index 4b9e96ec..fae0c9ca 100644 --- a/docs/java/jvm/memory-area.md +++ b/docs/java/jvm/memory-area.md @@ -103,23 +103,21 @@ Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共 Java 世界中“几乎”所有的对象都在堆中分配,但是,随着 JIT 编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。从 JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。 -Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(Garbage Collected Heap)**。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代;再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。**进一步划分的目的是更好地回收内存,或者更快地分配内存。** +Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(Garbage Collected Heap)**。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代;再细致一点有:Eden、Survivor、Old 等空间。**进一步划分的目的是更好地回收内存,或者更快地分配内存。** 在 JDK 7 版本及 JDK 7 版本之前,堆内存被通常分为下面三部分: 1. 新生代内存(Young Generation) 2. 老生代(Old Generation) -3. 永生代(Permanent Generation) +3. 永久代(Permanent Generation) -![JVM堆内存结构-JDK7](./pictures/java内存区域/JVM堆内存结构-JDK7.png) +下图所示的 Eden 区、两个 Survivor 区 S0 和 S1 都属于新生代,中间一层属于老年代,最下面一层属于永久代。 -JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。 +![hotspot-heap-structure](./pictures/java内存区域/hotspot-heap-structure.jpg) -![JVM堆内存结构-JDK8](./pictures/java内存区域/JVM堆内存结构-jdk8.png) +**JDK 8 版本之后 PermGen 已被 Metaspace(元空间) 取代,元空间使用的是直接内存。** -**上图所示的 Eden 区、两个 Survivor 区都属于新生代(为了区分,这两个 Survivor 区域按照顺序被命名为 from 和 to),中间一层属于老年代。** - -大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。 +大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 S0 或者 S1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。 > **🐛 修正(参见:[issue552](https://github.com/Snailclimb/JavaGuide/issues/552))** :“Hotspot 遍历所有对象时,按照年龄从小到大对其所占用的大小进行累积,当累积的某个年龄大小超过了 survivor 区的一半时,取这个年龄和 MaxTenuringThreshold 中更小的一个值,作为新的晋升年龄阈值”。 > @@ -141,7 +139,7 @@ JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 > } > ``` -堆这里最容易出现的就是 OutOfMemoryError 错误,并且出现这种错误之后的表现形式还会有几种,比如: +堆这里最容易出现的就是 `OutOfMemoryError` 错误,并且出现这种错误之后的表现形式还会有几种,比如: 1. **`java.lang.OutOfMemoryError: GC Overhead Limit Exceeded`** : 当 JVM 花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生此错误。 2. **`java.lang.OutOfMemoryError: Java heap space`** :假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发此错误。(和配置的最大堆内存有关,且受制于物理内存大小。最大堆内存可通过`-Xmx`参数配置,若没有特别配置,将会使用默认值,详见:[Default Java 8 max heap size](https://stackoverflow.com/questions/28272923/default-xmxsize-in-java-8-max-heap-size)) diff --git a/docs/java/jvm/pictures/java内存区域/JVM堆内存结构-JDK7.png b/docs/java/jvm/pictures/java内存区域/JVM堆内存结构-JDK7.png deleted file mode 100644 index bf0608bb..00000000 Binary files a/docs/java/jvm/pictures/java内存区域/JVM堆内存结构-JDK7.png and /dev/null differ diff --git a/docs/java/jvm/pictures/java内存区域/JVM堆内存结构-jdk8.png b/docs/java/jvm/pictures/java内存区域/JVM堆内存结构-jdk8.png deleted file mode 100644 index 307f3387..00000000 Binary files a/docs/java/jvm/pictures/java内存区域/JVM堆内存结构-jdk8.png and /dev/null differ diff --git a/docs/java/jvm/pictures/java内存区域/JVM运行时数据区域.png b/docs/java/jvm/pictures/java内存区域/JVM运行时数据区域.png index 4c6e6203..b460f23b 100644 Binary files a/docs/java/jvm/pictures/java内存区域/JVM运行时数据区域.png and b/docs/java/jvm/pictures/java内存区域/JVM运行时数据区域.png differ diff --git a/docs/java/jvm/pictures/java内存区域/Java创建对象的过程.png b/docs/java/jvm/pictures/java内存区域/Java创建对象的过程.png index 84f63955..178aa69f 100644 Binary files a/docs/java/jvm/pictures/java内存区域/Java创建对象的过程.png and b/docs/java/jvm/pictures/java内存区域/Java创建对象的过程.png differ diff --git a/docs/java/jvm/pictures/java内存区域/Java运行时数据区域JDK1.8.png b/docs/java/jvm/pictures/java内存区域/Java运行时数据区域JDK1.8.png index 14fe8a44..3491ece6 100644 Binary files a/docs/java/jvm/pictures/java内存区域/Java运行时数据区域JDK1.8.png and b/docs/java/jvm/pictures/java内存区域/Java运行时数据区域JDK1.8.png differ diff --git a/docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.drawio b/docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.drawio new file mode 100644 index 00000000..c2856142 --- /dev/null +++ b/docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.drawio @@ -0,0 +1 @@ +3ZZdb5swFIZ/jS8nGRy+LpuMrprUalqm7HJy8AGsGhsZZ0n262eCCaFQaZWitNoV+D3HH+d5j8CIrKrDF03r8lExEMjH7IDIZ+T7nodD+2iVY6ckSdQJhebMJQ3Cmv8BJ2Kn7jiDZpRolBKG12MxU1JCZkYa1Vrtx2m5EuNda1rARFhnVEzVn5yZslNjPxr0B+BF2e/shUkXqWif7CppSsrU/kIiKSIrrZTp3qrDCkQLr+fSzbt/JXo+mAZp/mVCsYH6SW3umdjEv75W+PvTqv7kVvlNxc4VnDKQ7sDm2FPQaicZtAt5iCz3JTewrmnWRvfWd6uVphIunHMhVkoofZpLWAAxW1i9MVo9w0Uk9rckDNvIM5is7KcraVwf2IrI0p0QtIHDq6V7Z6C2E0FVYPTRphzGzeR6kPTj/eCoFzqtvHSTOJG6LirOSw+g7Ytj/Qbu/oT7Gl+XOoU4z+aoh1kM2/wW1KMPh51MsXv/G3ZCPhz2xQT7D5A7bRlfk32eQ5jNsmdRssX49h+aYAb9Ir4p+miC/hvoisq2oKvCjzOYh7+Ng0XwDvAj/O7wvWBC/0GZpra/fB9vHpEf0qrFKrdNfWKAURqgO4ziEKURWi5RQlAaoiRF8WJilyVlxp6M2Usl4YVRTqKCF9IOM0sWrL5suXN76blzgYoz1m4z2wRDm+AXRgbXMTIZG+mTqZH+nJH+2320w+EGdopd3GNJ+hc= \ No newline at end of file diff --git a/docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.jpg b/docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.jpg new file mode 100644 index 00000000..2efc3da6 Binary files /dev/null and b/docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.jpg differ diff --git a/docs/java/jvm/pictures/java内存区域/《深入理解虚拟机》第三版的第2章-虚拟机栈.png b/docs/java/jvm/pictures/java内存区域/《深入理解虚拟机》第三版的第2章-虚拟机栈.png index 16e79e64..c8423db5 100644 Binary files a/docs/java/jvm/pictures/java内存区域/《深入理解虚拟机》第三版的第2章-虚拟机栈.png and b/docs/java/jvm/pictures/java内存区域/《深入理解虚拟机》第三版的第2章-虚拟机栈.png differ diff --git a/docs/java/jvm/pictures/java内存区域/内存分配的两种方式.png b/docs/java/jvm/pictures/java内存区域/内存分配的两种方式.png index ccc18601..b9b196e9 100644 Binary files a/docs/java/jvm/pictures/java内存区域/内存分配的两种方式.png and b/docs/java/jvm/pictures/java内存区域/内存分配的两种方式.png differ diff --git a/docs/java/jvm/pictures/java内存区域/字符串拼接-常量池.png b/docs/java/jvm/pictures/java内存区域/字符串拼接-常量池.png index 93321220..ede4a8da 100644 Binary files a/docs/java/jvm/pictures/java内存区域/字符串拼接-常量池.png and b/docs/java/jvm/pictures/java内存区域/字符串拼接-常量池.png differ diff --git a/docs/java/jvm/pictures/java内存区域/对象的访问定位-使用句柄.png b/docs/java/jvm/pictures/java内存区域/对象的访问定位-使用句柄.png index 7c773504..dfd6ef62 100644 Binary files a/docs/java/jvm/pictures/java内存区域/对象的访问定位-使用句柄.png and b/docs/java/jvm/pictures/java内存区域/对象的访问定位-使用句柄.png differ diff --git a/docs/java/jvm/pictures/java内存区域/对象的访问定位-直接指针.png b/docs/java/jvm/pictures/java内存区域/对象的访问定位-直接指针.png index 13a5f8a8..d9deabee 100644 Binary files a/docs/java/jvm/pictures/java内存区域/对象的访问定位-直接指针.png and b/docs/java/jvm/pictures/java内存区域/对象的访问定位-直接指针.png differ diff --git a/docs/java/jvm/pictures/jvm垃圾回收/01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png b/docs/java/jvm/pictures/jvm垃圾回收/01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png index 6a6d043f..26064a24 100644 Binary files a/docs/java/jvm/pictures/jvm垃圾回收/01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png and b/docs/java/jvm/pictures/jvm垃圾回收/01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png differ diff --git a/docs/java/jvm/pictures/jvm垃圾回收/25178350.png b/docs/java/jvm/pictures/jvm垃圾回收/25178350.png index be0f3d6d..e9b6a360 100644 Binary files a/docs/java/jvm/pictures/jvm垃圾回收/25178350.png and b/docs/java/jvm/pictures/jvm垃圾回收/25178350.png differ diff --git a/docs/java/jvm/pictures/jvm垃圾回收/29176325.png b/docs/java/jvm/pictures/jvm垃圾回收/29176325.png index e4406e15..dd4a54b6 100644 Binary files a/docs/java/jvm/pictures/jvm垃圾回收/29176325.png and b/docs/java/jvm/pictures/jvm垃圾回收/29176325.png differ diff --git a/docs/java/jvm/pictures/jvm垃圾回收/jvm-gc-roots.png b/docs/java/jvm/pictures/jvm垃圾回收/jvm-gc-roots.png index d0fd1390..c57f1e96 100644 Binary files a/docs/java/jvm/pictures/jvm垃圾回收/jvm-gc-roots.png and b/docs/java/jvm/pictures/jvm垃圾回收/jvm-gc-roots.png differ diff --git a/docs/java/jvm/pictures/jvm垃圾回收/rf-hotspot-vm-gc.png b/docs/java/jvm/pictures/jvm垃圾回收/rf-hotspot-vm-gc.png index 269ffe9b..13826205 100644 Binary files a/docs/java/jvm/pictures/jvm垃圾回收/rf-hotspot-vm-gc.png and b/docs/java/jvm/pictures/jvm垃圾回收/rf-hotspot-vm-gc.png differ diff --git a/docs/java/jvm/pictures/jvm垃圾回收/run-with-PrintGCDetails.png b/docs/java/jvm/pictures/jvm垃圾回收/run-with-PrintGCDetails.png index fee58383..a2c8438d 100644 Binary files a/docs/java/jvm/pictures/jvm垃圾回收/run-with-PrintGCDetails.png and b/docs/java/jvm/pictures/jvm垃圾回收/run-with-PrintGCDetails.png differ