浅析JVM垃圾收集回收机制

垃圾对象的判断

引用计数法

对象创建时,给该对象实例分配给一个变量,该变量计数设置为1。当该对象引用被调用时,计数加1,当其他变量不再被该对象引用赋值而设置为一个新值时,对象实例的引用计数器减1。任何引用计数器为0的对象实例可以被当作垃圾收集。当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器减1。

缺点:无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。

可达性分析法

根不可达即可回收

作为GCRoots的对象

  • 虚拟机栈中引用的对象(栈帧中的局部变量表);
  • 方法区的类静态属性所引用的对象
  • 方法区中常量所引用的对象
  • 本地方法栈中引用的对象

垃圾收集算法

标记-清除算法

从GC Roots扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,会造成大量内存碎片

复制算法

把可用的对象从一个地方拷贝到另一个地方,原来区域作为空闲区,适合大量对象回收的场景,比如新生代的回收。

标记-整理算法

在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的空闲指针

分代收集算法

根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代和新生代,在堆区之外还有一个代就是永久代。

年轻代:

  1. 所有新生成的对象首先都是放在年轻代的。
  2. 新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复。
  3. 当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代。若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收。
  4. 新生代发生的GC也叫做Minor GC(复制算法),MinorGC发生频率比较高(不一定等Eden区满了才触发)。

老年代:

在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。
内存比新生代也大很多(2倍),当老年代内存满时触发Major GC即Full GC(标记整理算法)

持久代:

用于存放静态文件,如Java类、方法等。

1.8中将字符串常量由永久代转移到堆中,并用元空间取代持久代。元空间并不在虚拟机中,而是使用本地内存。
因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:

  • -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  • -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
  • -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  • -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

垃圾收集器

Serial 收集器

标记-复制。
单线程,一个CPU或一条收集线程去完成垃圾收集工作,收集时必须暂停其他所有的工作线程,直到它结束。

虚拟机运行在Client模式下的默认新生代收集器。

ParNew 收集器

ParNew是Serial收集器的多线程版本。Server模式下默认新生代收集器,除了Serial收集器之外,只有它能与CMS收集器配合工作。

Parallel Scavenge 收集器

新生代收集器,复制算法。侧重于达到一个可控制的吞吐量,主要适合在后台运算而不需要太多交互的任务。

  • -XX:MaxGCPauseMillis 最大垃圾收集停顿时间
  • -XX:GCTimeRatio 吞吐量大小

Serial Old收集器

标记-整理算法。
单线程,是Serial收集器的老年代版本,给Client模式下的虚拟机使用。

Parallel Old 收集器

java8默认Parallel Scavenge+Parallel Old

CMS 收集器

标记-清除。
以获取最短回收停顿时间为目标,适用于互联网站或者B/S系统的服务端

  • 初始标记(CMS initial mark) -stop the world,标记GC Roots直接关联的对象
  • 并发标记(CMS concurrent mark)
  • 重新标记(CMS remark) -stop the world,GC Roots Tracing
  • 并发清除(CMS concurrent sweep)

你可能感兴趣的:(浅析JVM垃圾收集回收机制)