Java垃圾回收机制小结以及优化建议

什么情况下GC会执行


因为它对系统影响很明显,所以它到底在什么时候执行呢?

总的来说,有两个条件会触发主GC:

  1. 当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,但以下条件除外。

  2. Java堆内存不足时,GC会被调用。当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则 JVM将报“out of memory”的错误,Java应用将停止。

由于是否进行主GC由JVM根据系统环境决定,而系统环境在不断的变化当中,所以主GC的运行具有不确定性,无法预计它何时必然出现,但可以确定的是对一个长期运行的应用来说,其主GC是反复进行的。

垃圾回收的一般步骤


之前已经了解到Java堆被主要分成三个部分,而垃圾回收主要是在Young(年轻代)和Tenured(老年代)工作。 而 年轻代 又包括 Eden(伊利园)和两个Survivor(幸存者)。 下面我们就来看看这些空间是如何进行交互的:

1、首先,所有新生成的对象都是放在年轻代的Eden分区的,初始状态下两个Survivor分区都是空的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2、当Eden区满的的时候,小垃圾收集就会被触发。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3、当Eden分区进行清理的时候,会把引用对象移动到第一个Survivor分区,无引用的对象删除。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4、在下一个小垃圾收集的时候,在Eden分区中会发生同样的事情:无引用的对象被删除,引用对象被移动到另外一个Survivor分区(S1)。此外,从上次小垃圾收集过程中第一个Survivor分区(S0)移动过来的对象年龄增加,然后被移动到S1。当所有的幸存对象移动到S1以后,S0和Eden区都会被清理。注意到,此时的Survivor分区存储有不同年龄的对象。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5、在下一个小垃圾收集,同样的过程反复进行。然而,此时Survivor分区的角色发生了互换,引用对象被移动到S0,幸存对象年龄增大。Eden和S1被清理。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6、这幅图展示了从年轻代到老年代的提升。当进行一个小垃圾收集之后,如果此时年老对象此时到达了某一个个年龄阈值(例子中使用的是8),JVM会把他们从年轻代提升到老年代。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7、随着小垃圾收集的持续进行,对象将会被持续提升到老年代。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8、这样几乎涵盖了年轻一代的整个过程。最终,在老年代将会进行大垃圾收集,这种收集方式会清理-压缩老年代空间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

也就是说,刚开始会先在新生代内部反复的清理,顽强不死的移到老生代清理,最后都清不出空间,就爆炸了。

与堆配置相关的参数

| 参数 | 描述 |

| — | — |

| -Xms | JVM启动的时候设置初始堆的大小 |

| -Xmx | 设置最大堆的大小 |

| -Xmn | 设置年轻代的大小 |

| -XX:PermSize | 设置持久代的初始的大小 |

| -XX:MaxPermSize | 设置持久代的最大值 |

优化建议:

根据GC的工作原理,我们可以通过一些技巧和方式,让GC运行更加有效率

  1. 最基本的建议就是尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后,自动设置为 null。好的做法是:如果程序允许,尽早将不用的引用对象赋为null,这样可以加速GC的工作;

  2. 尽量少用finalize函数。finalize函数是Java提供给程序员一个释放对象或资源的机会。但是,它会加大GC的工作量,因此尽量少采用finalize方式回收资源;

  3. 如果需要使用经常使用的图片,可以使用SoftReference类型。它可以尽可能将图片保存在内存中,供程序调用,而不引起OutOfMemory;

  4. 注意集合数据类型,包括数组,树,图,链表等数据结构,这些数据结构对GC来说,回收更为复杂,所以使用结束应立即置为null,不要等堆在一起。另外,注意一些全局的变量,以及一些静态变量。这些变量往往容易引起悬挂对象(dangling reference),造成内存浪费;

  5. 当程序有一定的等待时间(注意,是有一定等待时间时),程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。使用增量式GC可以缩短Java程序的暂停时间。System.gc(); Runtime.getRuntime().gc() 这个方法对资源消耗较大尽量不要手动去调用这个方法,不然可能引起程序的明显卡顿

  6. 尽量使用StringBuffer,而不用String来累加字符串

  7. 能用基本类型如int,long,就不用Integer,Long对象。基本类型变量占用的内存资源比相应对象占用的少得多;

  8. 尽量少用静态对象变量,静态变量属于全局变量,不会被GC回收,它们会一直占用内存;

  9. 分散对象创建或删除的时间,集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM在面临这种情况时,只能进行主GC,以回收内存或整合内存碎片,从而增加主GC的频率。

合理使用 软引用 和 弱引用


清除 将引用对象的 referent 域设置为 null ,并将引用类在堆中引用的对象声明为 可结束的。 StrongReference 强引用:正常的对象,一直不会清理,直到爆炸。 SoftReference 软引用:内存不够的时候,遇到了就清了。 WeakReference 弱引用:只要遇到了就清了,注意:可能清了好几次,都没遇到。 PhantomReference 虚引用:虚顾名思义就是没有的意思,建立虚引用之后通过get方法返回结果始终为null。

PhantomReference 必须与 ReferenceQueue 类一起使用。需要 ReferenceQueue 是因为它能够充当通知机制。当垃圾收集器确定了某个对象是虚可及对象时, PhantomReference 对象就被放在它的 ReferenceQueue 上。将 PhantomReference 对象放在 ReferenceQueue 上也就是一个通知,表明 PhantomReference 对象引用的对象已经结束,可供收集了。这使您能够刚好在对象占用的内存被回收之前采取行动。

给个软引用的例子:

//首先定义一个HashMap,保存软引用对象。

private Map<String, SoftReference> imageCache = new HashMap<String, SoftReference>();

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

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

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

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

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

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

蚂蚁金服5面,总结了49个面试题,遇到的面试官都是P7级别以上

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

[外链图片转存中…(img-SeZof80C-1713132654601)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值