资讯专栏INFORMATION COLUMN

Java性能优化之垃圾回收机制

philadelphia / 1839人阅读

摘要:年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年老代在年轻代中经历了次垃圾回收后仍然存活的对象,就会被放到年老代中。什么情况下触发垃圾回收由于对象进行了分代处理,因此垃圾回收区域时间也不一样。

[TOC]

与C/C++相比,java语言不需要程序员直接控制内存回收,java程序的内存分配和回收都是由JRE在后台自动进行,JRE会负责回收那些不再使用的内存,这种机制被称为垃圾回收机制(Garbage Collection,GC):

主要负责两件事情

发现无用的对象

回收被无用对象占用的内存空间,使之再次被程序使用(一般是在CPU空闲或者内存不足时)。

事实上,除了释放没用对象占用的内存空间外,垃圾回收也可以清除内存纪录碎片(由于创建对象和垃圾回收器释放丢弃对象所占的内存空间)
特点

垃圾回收机制的工作目标是回收无用对象的内存空间,==这些内存空间都是jvm堆内存(运行时数据区,用以保存类的实例,即对象)里的内存空间==,不包含其它物力资源,比如数据库连接、磁盘I/O等;

Java语言没有显式的提供分配内存和删除内存的方法,一些开发人员将引用对象设置为null或者调用System.gc()或者Runtime.getRuntime.gc()来释放内存(==后两种方法仅是建议,慎重使用==);

垃圾回收不可预知,不同的jvm采用不同的垃圾回收机制和算法,有可能定时发生,有可能CPU空闲时发生,也有可能内存耗尽时发生

分代垃圾回收

年轻代(Young Generation)

所有新生成的对象首先都是放在年轻代的。

年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象

年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。大部分对象在Eden区中生成。

当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个)==(YGC,年轻代垃圾回收)==,当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。

需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。
同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。
年老代(Old Generation)

在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

持久代(Permanent Generation)

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。

什么情况下触发垃圾回收

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Minor GC和Full GC。

Minor GC

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Minor GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。
然后整理Survivor的两个区。

这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

Full GC

对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Minor GC要慢,因此应该尽可能减少Full GC的次数。

在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节。有如下原因可能导致Full GC:

年老代(Tenured)被写满

持久代(Perm)被写满

System.gc()被显示调用

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72261.html

相关文章

  • 手撕面试官系列(十一):BAT面试必备常问85题

    摘要:什么是线程饿死,什么是活锁多线程中的忙循环是什么变量是什么变量和变量有什么不同类型变量提供什么保证能使得一个非原子操作变成原子操作吗 JVM专题 showImg(https://segmentfault.com/img/remote/1460000019943435); (面试题+答案领取方式见个人主页) Java 类加载过程? 描述一下 JVM 加载 Class 文件的原理机制? ...

    CatalpaFlat 评论0 收藏0
  • JavaScript 闯关记》垃圾回收和内存管理

    摘要:内存回收此时,局部变量就没有存在的必要了,因此可以释放它们的内存以供将来使用。局部变量会在它们离开执行环境时自动被解除引用,如下面这个例子所示手工解除的引用由于局部变量在函数执行完毕后就离开了其执行环境,因此无需我们显式地去为它解除引用。 JavaScript 具有自动垃圾收集机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。而...

    Sleepy 评论0 收藏0
  • 性能优化(三)看完这篇文章,至少解决 APP 中 90 % 的内存异常问题

    摘要:不能满足被回收的条件,尽管调用也还是不能得到回收这就造成了内存泄漏。种解决单例中的内存泄漏将引用置为销毁监听使用弱引用将监听器放入弱引用中从弱引用中取出回调通过第七小点就能完美的解决单例中回调引起的内存泄漏。我们为什么要优化内存 showImg(https://user-gold-cdn.xitu.io/2019/5/12/16aac64e31d8c501); 在 Android 中我们写的...

    Elle 评论0 收藏0
  • 细述 Java垃圾回收机制→Types of Java Garbage Collectors

    摘要:并发标记清除垃圾回收器,使用多个线程来扫描堆内存并标记可被清除的对象,然后清除标记的对象。垃圾回收器应用于大的堆内存空间。它将堆内存空间划分为不同的区域,对各个区域并行地做回收工作。它会通过把重复的值移动到同一个数组来优化堆内存占用。 本文非原创,翻译自Types of Java Garbage Collectors在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的。...

    Julylovin 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<