5454
5555### 本文导火索
5656
57- ![ ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-26/ 29176325.jpg )
57+ ![ ] ( ./pictures/jvm垃圾回收/ 29176325.png )
5858
5959当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些"自动化"的技术实施必要的监控和调节。
6060
@@ -66,7 +66,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(G
6666
6767** 堆空间的基本结构:**
6868
69- ![ ] ( https://imgkr.cn-bj.ufileos.com /01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png)
69+ ![ ] ( ./pictures/jvm垃圾回收 /01d330d8-2710-4fad-a91c-7bbbfaaefc0e.png)
7070
7171上图所示的 Eden 区、From Survivor0("From") 区、To Survivor1("To") 区都属于新生代,Old Memory 区属于老年代。
7272
@@ -97,7 +97,7 @@ Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(G
9797
9898经过这次GC后,Eden区和"From"区已经被清空。这个时候,"From"和"To"会交换他们的角色,也就是新的"To"就是上次GC前的"From",新的"From"就是上次GC前的"To"。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到"To"区被填满,"To"区被填满之后,会将所有对象移动到老年代中。
9999
100- 
100+ 
101101
102102### 1.1 对象优先在 eden 区分配
103103
@@ -125,10 +125,10 @@ public class GCTest {
125125}
126126```
127127通过以下方式运行:
128- ![ ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-26/ 25178350.jpg )
128+ ![ ] ( ./pictures/jvm垃圾回收/ 25178350.png )
129129
130130添加的参数:` -XX:+PrintGCDetails `
131- ![ ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-26/ 10317146.jpg )
131+ ![ ] ( ./pictures/jvm垃圾回收/ 10317146.png )
132132
133133运行结果 (红色字体描述有误,应该是对应于 JDK1.7 的永久代):
134134
@@ -207,7 +207,7 @@ public class GCTest {
207207
208208堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。
209209
210- 
210+ 
211211
212212### 2.1 引用计数法
213213
@@ -236,7 +236,7 @@ public class ReferenceCountingGc {
236236
237237这个算法的基本思想就是通过一系列的称为 ** "GC Roots"** 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。
238238
239- ![ 可达性分析算法 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 72762049.jpg )
239+ ![ 可达性分析算法 ] ( ./pictures/jvm垃圾回收/ 72762049.png )
240240
241241
242242### 2.3 再谈引用
@@ -302,7 +302,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
302302
303303## 3 垃圾收集算法
304304
305- ![ 垃圾收集算法分类] ( https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/ 垃圾收集算法.jpg )
305+ ![ 垃圾收集算法分类] ( ./pictures/jvm垃圾回收/ 垃圾收集算法.png )
306306
307307### 3.1 标记-清除算法
308308
@@ -311,18 +311,18 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
3113111 . ** 效率问题**
3123122 . ** 空间问题(标记清除后会产生大量不连续的碎片)**
313313
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 )
315315
316316### 3.2 复制算法
317317
318318为了解决效率问题,"复制"收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。
319319
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 " >
321321
322322### 3.3 标记-整理算法
323323根据老年代的特点提出的一种标记算法,标记过程仍然与"标记-清除"算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
324324
325- ![ 标记-整理算法 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 94057049.jpg )
325+ ![ 标记-整理算法 ] ( ./pictures/jvm垃圾回收/ 94057049.png )
326326
327327### 3.4 分代收集算法
328328
@@ -336,7 +336,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
336336
337337## 4 垃圾收集器
338338
339- ![ 垃圾收集器分类] ( https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/ 垃圾收集器.jpg )
339+ ![ 垃圾收集器分类] ( ./pictures/jvm垃圾回收/ 垃圾收集器.png )
340340
341341** 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。**
342342
@@ -347,7 +347,7 @@ JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引
347347Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 ** "单线程"** 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( ** "Stop The World"** ),直到它收集结束。
348348
349349 ** 新生代采用复制算法,老年代采用标记-整理算法。**
350- ![ Serial 收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 46873026.jpg )
350+ ![ Serial 收集器 ] ( ./pictures/jvm垃圾回收/ 46873026.png )
351351
352352虚拟机的设计者们当然知道 Stop The World 带来的不良用户体验,所以在后续的垃圾收集器设计中停顿时间在不断缩短(仍然还有停顿,寻找最优秀的垃圾收集器的过程仍然在继续)。
353353
@@ -357,7 +357,7 @@ Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收
357357** ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。**
358358
359359 ** 新生代采用复制算法,老年代采用标记-整理算法。**
360- ![ ParNew 收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/ 22018368.jpg )
360+ ![ ParNew 收集器 ] ( ./pictures/jvm垃圾回收/ 22018368.png )
361361
362362它是许多运行在 Server 模式下的虚拟机的首要选择,除了 Serial 收集器外,只有它能与 CMS 收集器(真正意义上的并发收集器,后面会介绍到)配合工作。
363363
@@ -386,7 +386,7 @@ Parallel Scavenge 收集器也是使用复制算法的多线程收集器,它
386386** Parallel Scavenge 收集器关注点是吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。** Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解的话,手工优化存在困难的话可以选择把内存管理优化交给虚拟机去完成也是一个不错的选择。
387387
388388 ** 新生代采用复制算法,老年代采用标记-整理算法。**
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 )
390390
391391
392392### 4.4.Serial Old 收集器
@@ -408,7 +408,7 @@ Parallel Scavenge 收集器也是使用复制算法的多线程收集器,它
408408- ** 重新标记:** 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短
409409- ** 并发清除:** 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。
410410
411- ![ CMS 垃圾收集器 ] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-8-27/82825079.jpg )
411+ ![ CMS 垃圾收集器 ] ( ./pictures/jvm垃圾回收/CMS收集器.png )
412412
413413从它的名字就可以看出它是一款优秀的垃圾收集器,主要优点:** 并发收集、低停顿** 。但是它有下面三个明显的缺点:
414414
0 commit comments