Java垃圾回收

垃圾回收的意义

在C、C++ 中,对象所占的内存在程序结束运行之前一直被占用,除非被显式地释放。但是在Java中,java虚拟机具有自动内存管理机制,不需要为每一个new出来的对象显式地编写配对的delete/free内存的代码,由虚拟机区清理内存垃圾,不容易出现内存泄漏或者内存溢出的问题。

什么才是垃圾

通过可达性分析,通过一系列被称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots 没有任何引用链相连的时候证明此对象是不可用的,即为垃圾,可以被回收。

引用

Java语言对对象的引用方式:强引用、软引用、弱引用、虚引用

强引用: 类似 Object obj = new Object(),创建一个对象,并把对象赋值给一个引用变量。
软引用:用于描述一些还有用但又非必须的对象,这种引用在内存充足时不会被回收,当内存不足时才会被回收,常用于缓存。
弱引用:与软引用类似,但是生存时间更短,从创建开始只能存活到下一次内存回收之前
虚引用:虚引用不会对对象的生存周期产生影响,只能用于监控对象被回收的状态。

垃圾回收算法

标记清除算法

先将所有要被回收的对象进行标记,再对所有标记了的对象进行统一回收。

缺点:

  1. 标记和清除的效率都不高
  2. 标记清除后会产生大量不连续的内存碎片,空间碎片太多会导致以后在需要分配大对象的时候无法找到足够的连续内存而不得不触发另一次垃圾收集动作。

复制算法

将可用内存按容量划分为大小相等的两块,每次只使用其中一块,当这一块的内存用完了的时候,将存活着的对象复制到另外一块的上面,然后将已使用过的内存空间一次清理掉。

缺点:内存缩小了一半,对象存活率较高时需要进行较多的复制工作,效率将会变低。

标记整理算法

先对所有要被回收的对象进行标记,再让所有存活的对象都向一端移动,最后直接清理掉边界以外的内存。

分代收集算法

将java堆分为新生代和老年代,在新生代每次垃圾回收都会有大量的对象死去只有少量的存活,采用复制算法收集,老年代因为对象存活率高,采用标记整理算法收集。

垃圾收集器

垃圾收集器是 jvm 中内存回收的具体实现。

Serial收集器

串行收集器是最古老,最稳定以及效率高的收集器,只使用一个线程去回收。新生代、老年代使用串行回收;新生代采用复制算法、老年代采用标记-整理算法回收;在进行垃圾收集时必须暂停所有的用户线程,直至收集结束。

ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本。新生代并行,老年代串行;新生代采用复制算法、老年代采用标记-整理算法

Parallel收集器

Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量。新生代采用复制算法、老年代采用标记-整理算法。

系统吞吐量=运行用户代码的时间/(运行用户代码时间+垃圾收集时间)
因而Parallel收集器适用于进行后台运算而不需要进行太多交互的场景。

CMS收集器

CMS收集器是一种基于“标记-清除”算法实现的收集器,它的运作过程相对于前面几种收集器来说要更复杂一些,整个过程分为4个步骤,包括:

  1. 初始标记
  2. 并发标记
  3. 重新标记
  4. 并发清除

其中,初始标记和重新标记两个阶段需要暂停用户所有线程。

缺点:

  1. 对cpu资源比较敏感,占用了一部分线程导致应用程序变慢,总吞吐量会降低
  2. 无法处理浮动垃圾,在并发清理阶段,用户线程还会产生垃圾只能等待下一次GC。
  3. 标记清除算法本身会产生大量的空间碎片

G1收集器

G1是一款面向服务端应用的垃圾收集器,有如下特点:

  1. 并行与并发:充分利用多cpu,多核环境下的优势,缩短停顿时间。
  2. 分代收集:使用不同的方式处理新创建的对象和已经存活了一段时间的对象;
  3. 空间整合:Gc完成后不会产生内存空间的碎片;
  4. 可预测的停顿:可以让使用者明确指定垃圾收集时间不能超过n毫秒。

G1 收集器将java堆分成若干个大小相等的独立区域(Region),新生代和老年代之间不再是物理隔离,而是变成了一部分不连续的 Region 的集合。

G1 收集器执行大概分为四个步骤:

  1. 初始标记
  2. 并发标记
  3. 最终标记
  4. 筛选回收

初始标记阶段仅仅是标记一下GC Roots能直接关联到的对象,这一阶段需要停顿线程,但是耗时很短,并发标记阶段是从 GC Roots 出发对java堆中的对象进行可达性分析,找出存活的对象,这一阶段可以与用户线程并发执行,最终标记阶段是为了修正在并发标记阶段由于用户线程并发运行而产生变动的那一部分标记记录,而最终的筛选回收阶段则是对各个Region的回收价值和成本进行排序,再根据用户希望的GC停顿时间制定回收计划。

内存分配和回收策略

java技术体系的自动内存管理主要解决了两个问题:给对象分配内存和回收分配给对象的内存。

内存分配的策略有:

  1. 对象优先在Eden分配;
  2. 大对象直接进入老年代;
  3. 长期存活的对象将进入老年代;
  4. 动态对象年龄判定:如果survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于等于该年龄的对象可直接进入老年代。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值