jvm培训:垃圾回收的基本概念

    我们都知道调用System.gc()方法只是通知系统去回收,是否回收不能确定。     回收的判断     JVM中,将一个对象真正回收需经历两次标记过程,每次都是先判断对象有没有被持有引用,再...

    我们都知道调用System.gc()方法只是通知系统去回收,是否回收不能确定。


    回收的判断


    JVM中,将一个对象真正回收需经历两次标记过程,每次都是先判断对象有没有被持有引用,再判断对象是否必要执行finalize()方法。


    持有判断。最先使用是引用计数算法,当对象有一个引用,即增加一个计数;删除一个引用,即减少一个计数。计数为零的对象,判断为不可用,但是无法处理循环引用的问题。现主流的都是可达性分析算法,通过将一系列称为GCRoots的对象作为起始点,开始向下搜索,走过的路径则是引用链。若所有GCRoots都与某对象无引用链相连,即不可达时,判断为不可用。


    注意:GCRoots对象包括:虚拟机栈(栈帧中的本地变量表)中引用对象;方法区中类静态属性引用的对象;方法区中常量池引用的对象;本地方法栈(一般的本地方法,即JNI)中引用的对象。


    必要判断。当对象没有重写finalize()方法或者finalize()方法已被虚拟机调用过,都将视为“没有必要执行”。否则此对象将放置在F-Queue的队列中,由一个虚拟机自动建立的、低优先级的Finalizer线程去触发该方法,但不承诺等待它运行结束,以防执行缓慢或为死循环,导致队列其它对象永久等待,乃至内存回收系统崩溃。


    对F-Queue中对象进行二次标记。只要有对象重新与GCRoots对象关联,就会被移出队列,否则GC回收。


    垃圾收集算法


    当确定哪些垃圾可以被回收后,需要做的就是高效地进行垃圾回收。由于JVM没有给出明确的规定,各厂商实现方式不同,这里只讨论常见垃圾收集算法的核心思想。

1.jpg


    标记-清除算法,最基础的算法,分为两个阶段。标记阶段:标出所有需要被回收的对象;清除阶段:回收被标记对象所占用的空间。但容易产生大量内存碎片,导致无足够空间分配给大对象,从而提前触发垃圾收集动作。


    复制算法,为了解决标记-清除算法的缺陷。将可用内存按容量分为大小相等的两块,每次只使用其中的一块。当一块用完时,复制可用对象至另一块并清除自己的内存空间,从而避免出现内存碎片。但可用内存为实际的一半,利用率低;且当存活对象很多时,效率也会降低。


    标记-整理算法,吸取以上两种算法优点。标记阶段与标记-清除算法同阶段一致,整理阶段则将存活对象移向一端,再清理边界以外空间。


    分代收集算法,目前主流。根据对象存活的生命周期,将内存划分为两大区域。老年代:每次垃圾收集只有少量对象需回收,一般采用标记-整理算法;新生代:每次垃圾收集都有大量对象需回收,大部分采用复制算法。但空间上不是等大的两块,而是一块大的Eden区域,两块小的Survivor区域,每次只使用一大一小两区域。垃圾回收时,它们将内部存活对象都移至空闲的小区域并清理自己。


    垃圾收集器


    垃圾收集算法是理论,而垃圾收集器是实现。下面根据海子的文章列出HotSpot(JDK7)提供的几种垃圾收集器。


    Serial/SerialOld收集器是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法;SerialOld收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。


    ParNew收集器是Serial收集器的多线程版本,使用多个线程进行垃圾收集。


    ParallelScavenge/ParallelOld收集器是多线程(并行)收集器。ParallelScavenge收集器是针对新生代的收集器,它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量;ParallelOld收集器是针对老年代的收集器,使用多线程和Mark-Compact算法。


    CMS(CurrentMarkSweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。


    G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。


  推荐阅读:jvm培训:如何判断哪些对象需要回收?

    如果你想了解更多关于java架构师的专业知识,可以加入JAVA架构师交流群:1037935907,里面都是同行,有资源分享包括但不限于(分布式架构、高可扩展、高性能、高并 发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、Mysql 、Zookeeper、Tomcat、Docker、Dubbo、Nginx)。欢迎一到五年的工程师加入,合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

  • 发表于 2020-12-14 16:17
  • 阅读 ( 193 )
  • 分类:技术干货

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
JAVA Q&A
JAVA Q&A

173 篇文章

作家榜 »

  1. JAVA Q&A 173 文章
  2. 江南 1 文章
  3. 伯乐 0 文章
  4. 孤存 0 文章
  5. q21164340 0 文章
  6. 赫敏12 0 文章
  7. 子牙 0 文章
  8. 赫敏 0 文章