你了解JVM垃圾回收机制及其实现原理吗?一文带你深入探讨

引用类型

====

  1. **强引用:**发生 gc 的时候不会被回收

  2. **软引用:**有用但不是必须的对象,在发生内存溢出之前会被回收

  3. **弱引用:**有用但不是必须的对象,在下一次 GC 时会被回收

  4. **虚引用(幽灵引用/幻影引用):**无法通过虚引用获得对象用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知

垃圾辨别方法

======

  1. 引用计数器为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1当计数器为 0 时就可以被回收。缺点是不能解决循环引用的问题

  2. 可达性分析从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的

GC Roots,GC 的根集合, 是一组必须活跃的引用

可作为 GC Roots 的对象有:

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

垃圾收集算法

======

  1. **引用计数(Reference Counting)**原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数垃圾回收时,只用收集计数为 0 的对象缺点:无法处理循环引用问题

  2. **标记-清除(Mark-Sweep)**第一阶段从引用根节点开始标记所有被引用的对象第二阶段遍历整个堆,把未标记的对象清除缺点:此算法需要暂停整个应用,同时,会产生内存碎片

  3. **复制(Copying)**把内存空间划为两个相等的区域,每次只使用其中一个区域垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。此算法每次只处理正在使用中的对象因为复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题缺点:需要两倍内存空间

  4. 标记-整理(Mark-Compact)第一阶段从引用根节点开始标记所有被引用对象第二阶段遍历整个堆,将所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题

  5. **分代(Generational Collecting)**基于对对象生命周期分析后得出的垃圾回收算法把堆中对象分为年青代、年老化、持久代(JDK8 不存在持久代)对不同生命周期的对象使用不同的算法进行回收现在的垃圾回收器一般使用此算法

分代回收算法

======

起源:研究发现,大部分 java 对象只存活一小段时间,而存活下来的小部分 java 对象则会存活很长一段时间

简单来说,将堆分成两部分,年轻代用来存放新对象,当对象存活时间够长时,移动到年老代

堆的分代

====

  • 年轻代 Young Generation
  1. 默认占总空间的 1/3(通过 -XX:NewRatio 指定年轻代和老年代比例)

  2. 分为 Eden、To Survivor、From Survivor 三个区,默认占比 8:1:1(通过 -XX:SurvivorRatio 指定)

  • 年老代 Tenured Generation
  1. 默认占总空间的 2/3
  • 持久代 Perm Generation(JDK8后不存在)
  1. 即方法区,用于存放静态文件,如今Java类、方法等

  2. 持久代对垃圾回收没有显著影响在

  3. JDK8 中,废弃了持久代,改用元空间(metaspace)实现方法区,属于本地内存

分代收集

====

  • 年轻代回收器
  1. 假设大部分对象都存活很短时间,需要频繁采用耗时较短的垃圾回收算法

  2. 新生代垃圾收集器一般采用复制算法,优点是效率高,缺点是内存利用率低

  3. 垃圾收集器有:Serial、ParNew、Parallel Scavenge

  • 年老代回收器
  1. 假设老年代中的对象大概率继续存活,真正触发老年代 gc 时,代表假设出错或堆空间已耗尽,一般需要全堆扫描,全局垃圾回收

  2. 老年代收集器一般采用的是标记-整理的算法进行垃圾回收

  3. 垃圾收集器有:Serial Old、Parallel Old、CMS

  • 整堆回收器

G1:兼顾吞吐量和停顿时间的 GC 实现,JDK 9 以后的默认 GC 选项

回收过程

====

新对象存放在年轻代的 Eden 分区,Eden 空间耗尽时,触发 gc,一般使用复制算法

年老代空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法

  1. 把 Eden 和 From Survivor 存活的对象放入 To Survivor 区

  2. 清空 Eden 和 From Survivor 分区

  3. From 和 To 交换指针,保证下次 gc 前To Survivor 为空

  4. Survivor 分区的对象,经过一次复制年龄就 +1,年龄到达 15时(默认 15),Survivor 分区升级为老生代。对象也会直接进入年老代

gc 类型

=====

  • Minor GC
  1. 一般情况下,当新对象生成,并且在 Eden 申请空间失败时,就会触发Minor GC

  2. 在年轻代 Eden 区域进行GC,清除不存活对象,并且把尚且存活的对象移动到 Survivor 区。然后整理 Survivor 的两个区

  3. 很频繁的 gc,不影响老年代

  • Full GC

对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:

  • Tenured 被写满

  • Perm 域被写满(JDK8 之前)

  • System.gc( ) 被显示调用

  • 上一次 GC 之后对的各域分配策略动态变化

垃圾收集器

=====

收集器分类

=====

  • 串行收集器
  1. 使用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高

  2. 无法使用多处理器的优势,所以适合单处理器机器,也可以用在小数据量情况下的多处理器机器

  3. 可以使用 -XX:+UseSerialGC 打开

  • 并发收集器
  1. 对年轻代进行并行垃圾回收,可以减少垃圾回收时间。一般在多线程多处理器机器上使用使用 -XX:+UseParallelGC打开

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

结语

小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

送给每一位想学习Java小伙伴,用来提升自己。

在这里插入图片描述

本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!
互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

送给每一位想学习Java小伙伴,用来提升自己。

[外链图片转存中…(img-6JE1zoIz-1712059053189)]

本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值