Java GC调优 基础

Garbage(垃圾)

1.定义:

1、如果对象没有任何引用,则该对象为垃圾。

2、循环引用的对象,没有外来引用。

2.如何寻找垃圾?

​ 1.reference count 引用计数

​ 2.Root Searching 根可达算法

啥叫root?

GC roots包括线程栈变量 静态变量 常量池 JNI指针等

凡是不能被根引用到的 都算是 garbage。

3.常见的垃圾回收算法

  • Mark-Sweep(标记清除)

    ​ 找到垃圾,然后标记,然后清除。位置不连续,容易产生碎片

  • Copying(拷贝)

    ​ 把内存区域分成两部分,分别使用。效率高,但浪费空间。

  • Mark-Compact(标记压缩)

    ​ 没有碎片,效率比copy略低。

4.JVM分代算法

  • 新生代+ 老年代 + 元数据区(1.8)

    • 元数据存储class
      • 元数据可设置也可不设置。(上限受限于物理内存)
  • 内存逻辑分区

    啥叫新生代啥又叫老年代呢?

    比如奥特赛文就是老年代,他儿子赛罗奥特曼就是新生代了——

    Saluo奥特曼

不皮了,我们看看这个:

堆内存逻辑分区

新生代是指左边的eden和两个survivor区,而老年代就是右边的old。一般新生代和老年代的大小比例是1:3。

MinorGC = Minor Garbage collect 新生代进行的垃圾回收

MajorGC = Major Garbage Collect 老年代进行的垃圾回收

当一个对象被创建出来之后,它就会进入新生代的eden。一段时间后,Eden就会把除了垃圾之外的对象复制到survivor(我们称之为s0)中,然后再把Eden清空。再又一段时间后,又进行一次Minor GC,又把Eden中除了垃圾之外的对象复制到另一个survivor(这叫s1),再把Eden清空。再之后,重复上述步骤。

像这样如此往复,当对象的年龄足够大之后,就会发往老年代(tuenured)

Eden和survivor的大小比是8:1:1。新生代的垃圾回收算法使用的是Copying,效率相对较高,而且其内部内存的分配又能有效地节约空间。

可能有人已经注意到了,如果eden放不下那个新的对象咋办?如果这样,那个对象将被直接发往老年代。

为了更好地适应不同程序内存状况,虚拟机并不硬性要求对象年龄达到MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入年老代。

​ 老年代:

​ 1.一直在重复的复制的

​ 2.老年代充满了FGC

FGC 即FULL GC,也成MajorGC会使用Mark Compact算法,其效率较低。赢尽量减少FGC的次数。

5.常见的垃圾回收器

新生代

Serial

​ 程序运行一段时间,当Eden内存满了之后,程序就会停止(stop-the-world),进行一次垃圾回收,然后程序继续运行。周而复始。用于年轻代,单线程,串行回收。

STW - STW阶段,应用程序线程被暂停,以便gc执行其工作。

Parallel Scavenge

​ 同Serial,但其进行的是串行回收。

ParNew

​ 用户配合CMS回收

老年代

SerialOld 同新生代

ParallelOld 同新生代

CMS 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)

垃圾

更新的GC:

  1. G1(10ms)
  2. ZGC (1ms) PK C++
  3. Shenandoah
  4. Eplison

ZGC具体可查阅https://wiki.openjdk.java.net/display/zgc/Main

1.8默认的垃圾回收:PS + ParallelOld

posted @ 2020-03-20 17:06  吉姆雷诺  阅读(157)  评论(0编辑  收藏  举报