[docs update]jvm垃圾回收部分图片重新绘制
@ -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 规范。
|
||||
|
||||

|
||||

|
||||
|
||||
#### JDK 和 JRE
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
---
|
||||
title: JVM 垃圾回收详解
|
||||
category: Java
|
||||
tag:
|
||||
- JVM
|
||||
---
|
||||
|
||||
# JVM 垃圾回收详解
|
||||
|
||||
## 写在前面
|
||||
|
||||
### 本节常见面试题
|
||||
|
@ -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)
|
||||
|
||||

|
||||
下图所示的 Eden 区、两个 Survivor 区 S0 和 S1 都属于新生代,中间一层属于老年代,最下面一层属于永久代。
|
||||
|
||||
JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。
|
||||

|
||||
|
||||

|
||||
**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))
|
||||
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 33 KiB |
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2022-02-10T06:48:11.793Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="Cw0G1kXam1WciRT-fe2O" version="13.4.5" type="device"><diagram id="iqBQqmSUkrwKoGtfJ_L6" name="Page-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=</diagram></mxfile>
|
BIN
docs/java/jvm/pictures/java内存区域/hotspot-heap-structure.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 430 KiB After Width: | Height: | Size: 165 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |