54
54
55
55
### 本文导火索
56
56
57
- ![ ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-26/ 29176325.jpg )
57
+ ![ ] ( ./pictures/jvm垃圾回收/ 29176325.png )
58
58
59
59
当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。
60
60
@@ -66,7 +66,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(G
66
66
67
67
** 堆空间的基本结构:**
68
68
69
- ![ ] ( https://imgkr.cn-bj.ufileos.com /01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png)
69
+ ![ ] ( ./pictures/jvm垃圾回收 /01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png)
70
70
71
71
上图所示的 Eden 区、From Survivor0("From") 区、To Survivor1("To") 区都属于新生代,Old Memory 区属于老年代。
72
72
@@ -97,7 +97,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(G
97
97
98
98
经过这次GC后,Eden区和"From"区已经被清空。这个时候,"From"和"To"会交换他们的角色,也就是新的"To"就是上次GC前的“From”,新的"From"就是上次GC前的"To"。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,"To"区被填满之后,会将所有对象移动到老年代中。
99
99
100
- 
100
+ 
101
101
102
102
### 1.1 对象优先在 eden 区分配
103
103
@@ -125,10 +125,10 @@ public class GCTest {
125
125
}
126
126
```
127
127
通过以下方式运行:
128
- ![ ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-26/ 25178350.jpg )
128
+ ![ ] ( ./pictures/jvm垃圾回收/ 25178350.png )
129
129
130
130
添加的参数:` -XX:+PrintGCDetails `
131
- ![ ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-26/ 10317146.jpg )
131
+ ![ ] ( ./pictures/jvm垃圾回收/ 10317146.png )
132
132
133
133
运行结果 (红色字体描述有误,应该是对应于 JDK1.7 的永久代):
134
134
@@ -207,7 +207,7 @@ public class GCTest {
207
207
208
208
堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。
209
209
210
- 
210
+ 
211
211
212
212
### 2.1 引用计数法
213
213
@@ -236,7 +236,7 @@ public class ReferenceCountingGc {
236
236
237
237
这个算法的基本思想就是通过一系列的称为 ** “GC Roots”** 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。
238
238
239
- ![ 可达性分析算法 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 72762049.jpg )
239
+ ![ 可达性分析算法 ] ( ./pictures/jvm垃圾回收/ 72762049.png )
240
240
241
241
242
242
### 2.3 再谈引用
@@ -302,7 +302,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
302
302
303
303
## 3 垃圾收集算法
304
304
305
- ![ 垃圾收集算法分类] ( https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/ 垃圾收集算法.jpg )
305
+ ![ 垃圾收集算法分类] ( ./pictures/jvm垃圾回收/ 垃圾收集算法.png )
306
306
307
307
### 3.1 标记-清除算法
308
308
@@ -311,18 +311,18 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
311
311
1 . ** 效率问题**
312
312
2 . ** 空间问题(标记清除后会产生大量不连续的碎片)**
313
313
314
- < img src = " http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/63707281.jpg " alt = " 公众号 " width = " 500px " >
314
+ ![ ] ( ./pictures/jvm垃圾回收/标记-清除算法.jpeg )
315
315
316
316
### 3.2 复制算法
317
317
318
318
为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。
319
319
320
- <img src =" http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 90984624.jpg " alt =" 公众号 " width =" 500px " >
320
+ <img src =" ./pictures/jvm垃圾回收/ 90984624.png " alt =" 公众号 " width =" 500px " >
321
321
322
322
### 3.3 标记-整理算法
323
323
根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
324
324
325
- ![ 标记-整理算法 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 94057049.jpg )
325
+ ![ 标记-整理算法 ] ( ./pictures/jvm垃圾回收/ 94057049.png )
326
326
327
327
### 3.4 分代收集算法
328
328
@@ -336,7 +336,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
336
336
337
337
## 4 垃圾收集器
338
338
339
- ![ 垃圾收集器分类] ( https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/ 垃圾收集器.jpg )
339
+ ![ 垃圾收集器分类] ( ./pictures/jvm垃圾回收/ 垃圾收集器.png )
340
340
341
341
** 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。**
342
342
@@ -347,7 +347,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
347
347
Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 ** “单线程”** 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( ** "Stop The World"** ),直到它收集结束。
348
348
349
349
** 新生代采用复制算法,老年代采用标记-整理算法。**
350
- ![ Serial 收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 46873026.jpg )
350
+ ![ Serial 收集器 ] ( ./pictures/jvm垃圾回收/ 46873026.png )
351
351
352
352
虚拟机的设计者们当然知道 Stop The World 带来的不良用户体验,所以在后续的垃圾收集器设计中停顿时间在不断缩短(仍然还有停顿,寻找最优秀的垃圾收集器的过程仍然在继续)。
353
353
@@ -357,7 +357,7 @@ Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收
357
357
** ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。**
358
358
359
359
** 新生代采用复制算法,老年代采用标记-整理算法。**
360
- ![ ParNew 收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 22018368.jpg )
360
+ ![ ParNew 收集器 ] ( ./pictures/jvm垃圾回收/ 22018368.png )
361
361
362
362
它是许多运行在 Server 模式下的虚拟机的首要选择,除了 Serial 收集器外,只有它能与 CMS 收集器(真正意义上的并发收集器,后面会介绍到)配合工作。
363
363
@@ -386,7 +386,7 @@ Parallel Scavenge 收集器也是使用复制算法的多线程收集器,它
386
386
** Parallel Scavenge 收集器关注点是吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。** Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解的话,手工优化存在困难的话可以选择把内存管理优化交给虚拟机去完成也是一个不错的选择。
387
387
388
388
** 新生代采用复制算法,老年代采用标记-整理算法。**
389
- ![ Parallel Scavenge 收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/22018368.jpg )
389
+ ![ Parallel Scavenge 收集器 ] ( ./pictures/jvm垃圾回收/parllel-scavenge收集器.png )
390
390
391
391
392
392
### 4.4.Serial Old 收集器
@@ -408,7 +408,7 @@ Parallel Scavenge 收集器也是使用复制算法的多线程收集器,它
408
408
- ** 重新标记:** 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短
409
409
- ** 并发清除:** 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。
410
410
411
- ![ CMS 垃圾收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/82825079.jpg )
411
+ ![ CMS 垃圾收集器 ] ( ./pictures/jvm垃圾回收/CMS收集器.png )
412
412
413
413
从它的名字就可以看出它是一款优秀的垃圾收集器,主要优点:** 并发收集、低停顿** 。但是它有下面三个明显的缺点:
414
414
0 commit comments