文档章节

GC和垃圾回收器其一

春哥大魔王的博客
 春哥大魔王的博客
发布于 07/22 12:03
字数 1981
阅读 8
收藏 0

什么是GC

GC(Garbage Collection)垃圾回收,释放垃圾占用的空间,对堆中已经死亡或者长时间没有使用的对象进行清除和回收,防止内存泄漏。可以有效使用内存空间。

什么是垃圾

垃圾收集之前需要定义什么是垃圾,之后才能决定如何回收垃圾。

抛开书面上介绍的几种垃圾分析算法,一步到位说下jvm采用的可达性分析法

可达性分析

基本思路是通过根引用(GC ROOT)作为分析起点,沿着节点向下搜索,搜索路径称为引用链(Reference Chain),当一个对象到GC ROOT没有任何引用链时,证明对象不再使用(GC ROOT到对象节点不可达)。

通过可达性分析算法可以解决引用计数无法解决的“循环依赖”,只要对象和GC ROOT之间无法建立直接或者间接的链接,就可以认定为可回收对象。

GC ROOT

既然GC ROOT在对象可达性分析时如此重要,那么哪些对象可以作为GC ROOT呢?

在之前需要先了解下JVM的内部结构:

以下四种情况可以认定为GC ROOT:

  • 虚拟机栈(栈帧的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(Native方法)引用的对象

垃圾回收

在确定垃圾之后就可以进行垃圾回收了,回收过程中最重要的一点就是如何高效的回收,这些也都是不同版本回收器进化的主要目标。

常见的垃圾收集算法:

  • 标记清除
  • 复制算法
  • 标记整理

标记清除

标记清除(Mark-Sweep)是将内存中认定为垃圾的对象进行标记,之后对这些标记的对象进行清理,清理之后的空间可以给新对象使用。

但是这种操作算法存在的问题会存在大量不连续的清理空间,也就是内存碎片。内存碎片带来的问题是,有的时候我们进行对象分配时,需要连续的内存(比如数组这种)但是由于内存中没有足够的联系内存,导致碎片内存用不了,造成了内存空间的浪费。

复制算法

复制(Copying)是在标记清除之上演进而来的,主要目的是解决内存碎片问题,将可用内存空间按照容量进行划分成大小相等的两块,每次只是用其中一块,当这部分内存使用完成之后,可以把存活对象复制到另一块上面,把之前使用的内存进行一次性清理,保证内存空间连续可用,复制算法我们可以不考虑内存碎片等问题,分配过程更简单高效。

但是复制算法带来的就是空间的代价更大。

标记整理

既然标记清除,复制算法都存在一些明确的短板,是否可以针对这些短板设计一个回收算法呢?于是就有了标记整理算法(Mark-Compact)。

标记整理过程和标记清除算法一样,但是后续整理方式是将存活对象统一移动到内存到一侧,在进行边界外的对象清除。

这种算法属于标记清除算法的升级版本,可以解决内存碎片问题,也避免了复制算法存在一半空间浪费的问题,但是也不是没有问题。首先他会造成更多的内存变动,比如需要判断存活对象,整理存活对象地址,效率上对于复制算法来说要差很多。

分代回收

我们了解了三种收集算法,JVM内存回收就可以根据自己特点进行算法选择了。

比如JVM根据对象存活周期不同将内存划分成不同的几部分。比如堆中针对于快生快消特点分出了新生代,存活较久对象分出了老年代。于是针对不同代对象特点可以选择不同的回收算法,比如年轻代对象生命周期比较短,可选择复制算法减少标记整理的代价。老年代存活对象较多,空间利用率上相对要求较高,需要使用标记清理或者标识整理算法。

JVM内存模型

那么JVM中对象具体是怎么分配的呢?从内存模型讲起。

堆是内存中最大的一块,也是垃圾回收的主要战场。

堆主要分为两个区域:年轻代和老年代,年轻代又分为Eden,s1,s2区。

Eden

新生对象优先在Eden中分配,当Eden中没有足够空间后,会触发一次YGC(比较讨厌用Minor GC和Major GC的说法),YGC之后Eden区被回收,无需回收的对象进入S1区,如果S1区容不下则直接进入老年代。

S区

S区主要作用是作为Eden和Old之间的缓冲带,因为之前说过Eden大部分对象都是短生命的,所以为了避免YGC之后直接进入老年代,引入S区也是有必要的,缓冲了因为频繁YGC使得老年代被填满的风险。

因为一而再再而三之后大部分对象还是在新生代消亡了,所以设置一个S区是明智的。

一般对象需要经过15(默认)YGC之后才进入老年代。

而两个S区的目的就是为了采用复制算法,来解决碎片问题。如果一个区域的话你就只能采取标记整理或标记清除算法了,为了降低YGC期间(因为YGC太频繁了)对于程序的影响,用复制算法这种简单可依赖的方式还有有必要的。

如果分成好几个S区会有什么问题呢?频繁的复制是个问题,过多的S区空间造成整体空间利用率更低也是个问题,相信这个2的阈值也是经过多次实验得来的,所以GC的很多默认算法其实是很优的配置,除非结合自己业务特点,否则比建议进行修改。

Old区

默认老年代占用整个区的2/3,只有发生Full GC(这个说法也不准确,我们用CMS回收器,所以就称为CMS GC吧)时才进行整理,Full GC会造成STW,内存越大STW肯定时间就越长(这个也是我们调优JVM参数一个很重要的参考点),所以内存并不是越大越好。上面说了老年代存在大量长期对象,所以采用标记算法更合适。

哪些对象会进入老年代?

  • 内存担保,无法放置对象直接进入老年代
  • 大对象直接进入老年代,可配置
  • 长期存活对象进入老年代,比如age=15
  • 动态对象年龄进入老年代,主要是s区空间不足了,某一个年龄及以上对象大小总和大于整个S区一半,这些年龄的对象直接进入老年代

© 著作权归作者所有

春哥大魔王的博客
粉丝 40
博文 296
码字总数 268636
作品 0
海淀
程序员
私信 提问
一个性能较好的JVM参数配置

一个性能较好的JVM参数配置 G1垃圾收集器(-XX:+UseG1GC) G1(Garbage First):垃圾收集器是在Java 7后才可以使用的特性,它的长远目标时代替CMS收集器。G1收集器是一个并行的、并发的和增量...

八戒_o
2016/02/22
124
0
Java GC系列:Java垃圾回收详解

Java的内存分配与回收全部由JVM垃圾回收进程自动完成。与C语言不同,Java开发者不需要自己编写代码实现垃圾回收。这是Java深受大家欢迎的众多特性之一,能够帮助程序员更好地编写Java程序。 ...

满风
2015/04/10
563
0
Java和.NET中的垃圾回收机制比较

相同点: 都采用了分代的机制。 都支持并发GC。 都没有采用引用计数方式,而是采用了追踪技术。 .NET中,可以通过代码GC.Collect() 强制要求CLR进行垃圾回收(由于垃圾回收是异步的,CLR有一...

cnn237111
2015/05/30
0
0
Java垃圾回收机制

一、垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃...

任任任任师艳
2017/11/17
0
0
JAVA垃圾回收机制概要

垃圾回收是JAVA中的一个大知识点,也是一个著名知识点,毕竟JAVA号称自己先进性的时候总是会带上垃圾回收。于是,它也成了面试中的常客,面试官动不动的就要你解释下什么是垃圾回收,以及它的...

文艺小青年
2017/06/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
146
8
SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
18
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
11
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部