IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> JVM - 垃圾回收 -> 正文阅读

[PHP知识库]JVM - 垃圾回收

垃圾回收

  1. 如何判断对象可以回收
  2. 垃圾回收算法
  3. 分代垃圾回收
  4. 垃圾回收器
  5. 垃圾回收调优

1. 如何判断对象可以回收

1.1 引用计数法

在这里插入图片描述

问题: A -> B, B -> A, 除此外无任何对象引用A和B。

1.2 可达性分析算法

  • Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
  • 扫描堆中的对象,看是否能够沿着 GC Root对象 为起点的引用链找到该对象,找不到,表示可以回收
  • 哪些对象可以作为 GC Root?

MAT工具:https://www.eclipse.org/mat/

jmap抓取内存快照:

# b表示转储文件为二进制格式,live表示只抓取存活对象(抓快照之前会触发垃圾回收),file表示保存的文件名称
jmap -dump:format=b,live,file=[fileName.formatName] [pid]

1.3 四种引用

在这里插入图片描述

实线表示强引用,其他表示软弱虚终几种引用。

1. 强引用
  • 只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收
2. 软引用(SoftReference)
  • 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用对象
  • 可以配合引用队列来释放软引用自身
3. 弱引用(WeakReference)
  • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
  • 可以配合引用队列来释放弱引用自身
4. 虚引用(PhantomReference)
  • 必须配合引用队列使用,主要配合 ByteBuffer 使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存
5. 终结器引用(FinalReference)
  • 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize方法,第二次 GC 时才能回收被引用对象

软引用使用场景栗子:

package top.onefine.jvm.test.t2;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class Demo2_3 {

    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) throws IOException {
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new byte[_4MB]);
        }

        System.in.read();
    }

}

JVM参数:
在这里插入图片描述
运行:
在这里插入图片描述
软引用:

package top.onefine.jvm.test.t2;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class Demo2_3 {

    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) throws IOException {
        /*List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new byte[_4MB]);
        }

        System.in.read();*/
        soft();
    }

    public static void soft() {
        // list --> SoftReference --> byte[]

        List<SoftReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }
        System.out.println("循环结束:" + list.size());

        for (SoftReference<byte[]> ref : list) {
            System.out.println(ref.get());
        }
    }
}

JVM参数:
在这里插入图片描述
运行:

[B@15db9742
1
[B@6d06d69c
2
[B@7852e922
3
[B@4e25154f
4
[GC (Allocation Failure) --[PSYoungGen: 4998K->4998K(6144K)] 17286K->17406K(19968K), 0.0011695 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4998K->4532K(6144K)] [ParOldGen: 12408K->12390K(13824K)] 17406K->16923K(19968K), [Metaspace: 2654K->2654K(1056768K)], 0.0046520 secs] [Times: user=0.20 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) --[PSYoungGen: 4532K->4532K(6144K)] 16923K->16975K(19968K), 0.0008806 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 4532K->0K(6144K)] [ParOldGen: 12442K->527K(8192K)] 16975K->527K(14336K), [Metaspace: 2654K->2654K(1056768K)], 0.0044023 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[B@70dea4e
5
循环结束:5
null
null
null
null
[B@70dea4e
Heap
 PSYoungGen      total 6144K, used 4265K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
  eden space 5632K, 75% used [0x00000000ff980000,0x00000000ffdaa598,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 8192K, used 527K [0x00000000fec00000, 0x00000000ff400000, 0x00000000ff980000)
  object space 8192K, 6% used [0x00000000fec00000,0x00000000fec83c30,0x00000000ff400000)
 Metaspace       used 2664K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 283K, capacity 386K, committed 512K, reserved 1048576K

软引用配合引用队列:

package top.onefine.jvm.test.t2;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用, 配合引用队列
 */
public class Demo2_4 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList<>();

        // 引用队列
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }

        // 从队列中获取无用的 软引用对象,并移除
        Reference<? extends byte[]> poll = queue.poll();
        while (poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }

        System.out.println("===========================");
        for (SoftReference<byte[]> reference : list) {
            System.out.println(reference.get());
        }

    }
}

JVM参数:

在这里插入图片描述

运行:

[B@15db9742
1
[B@6d06d69c
2
[B@7852e922
3
[B@4e25154f
4
[GC (Allocation Failure) --[PSYoungGen: 4998K->4998K(6144K)] 17286K->17422K(19968K), 0.0012145 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4998K->4548K(6144K)] [ParOldGen: 12424K->12374K(13824K)] 17422K->16922K(19968K), [Metaspace: 2652K->2652K(1056768K)], 0.0048164 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) --[PSYoungGen: 4548K->4548K(6144K)] 16922K->17018K(19968K), 0.0009279 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 4548K->0K(6144K)] [ParOldGen: 12470K->526K(8192K)] 17018K->526K(14336K), [Metaspace: 2652K->2652K(1056768K)], 0.0046568 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[B@70dea4e
5
===========================
[B@70dea4e
Heap
 PSYoungGen      total 6144K, used 4265K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
  eden space 5632K, 75% used [0x00000000ff980000,0x00000000ffdaa598,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 8192K, used 526K [0x00000000fec00000, 0x00000000ff400000, 0x00000000ff980000)
  object space 8192K, 6% used [0x00000000fec00000,0x00000000fec83bf0,0x00000000ff400000)
 Metaspace       used 2662K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 283K, capacity 386K, committed 512K, reserved 1048576K

弱引用栗子:

package top.onefine.jvm.test.t2;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示弱引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class Demo2_5 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        //  list --> WeakReference --> byte[]
        List<WeakReference<byte[]>> list = new ArrayList<>();

        for (int i = 0; i < 15; i++) {
            WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
            list.add(ref);
            for (WeakReference<byte[]> w : list) {
                System.out.print(w.get() + " ");
            }
            System.out.println();

        }
        System.out.println("循环结束:" + list.size());
    }
}

JVM参数:
在这里插入图片描述
运行:

[B@15db9742 
[B@15db9742 [B@6d06d69c 
[B@15db9742 [B@6d06d69c [B@7852e922 
[B@15db9742 [B@6d06d69c [B@7852e922 [B@4e25154f 
[GC (Allocation Failure) [PSYoungGen: 4998K->496K(6144K)] 17286K->12928K(19968K), 0.0012578 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null [B@6d06d69c [B@7852e922 [B@4e25154f [B@70dea4e 
[GC (Allocation Failure) [PSYoungGen: 4704K->480K(6144K)] 17136K->12968K(19968K), 0.0004862 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null [B@6d06d69c [B@7852e922 [B@4e25154f null [B@5c647e05 
[GC (Allocation Failure) [PSYoungGen: 4688K->512K(6144K)] 17176K->13032K(19968K), 0.0006619 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null [B@6d06d69c [B@7852e922 [B@4e25154f null null [B@33909752 
[GC (Allocation Failure) [PSYoungGen: 4719K->480K(6144K)] 17239K->13056K(19968K), 0.0006388 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null [B@6d06d69c [B@7852e922 [B@4e25154f null null null [B@55f96302 
[GC (Allocation Failure) [PSYoungGen: 4686K->496K(6144K)] 17263K->13088K(19968K), 0.0003781 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null [B@6d06d69c [B@7852e922 [B@4e25154f null null null null [B@3d4eac69 
[GC (Allocation Failure) [PSYoungGen: 4702K->496K(5120K)] 17294K->13104K(18944K), 0.0003471 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null [B@6d06d69c [B@7852e922 [B@4e25154f null null null null null [B@42a57993 
[GC (Allocation Failure) [PSYoungGen: 4682K->64K(5632K)] 17290K->13080K(19456K), 0.0004060 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 64K->0K(5632K)] [ParOldGen: 13016K->538K(8192K)] 13080K->538K(13824K), [Metaspace: 2656K->2656K(1056768K)], 0.0042214 secs] [Times: user=0.20 sys=0.00, real=0.00 secs] 
null null null null null null null null null null [B@75b84c92 
null null null null null null null null null null [B@75b84c92 [B@6bc7c054 
null null null null null null null null null null [B@75b84c92 [B@6bc7c054 [B@232204a1 
null null null null null null null null null null [B@75b84c92 [B@6bc7c054 [B@232204a1 [B@4aa298b7 
[GC (Allocation Failure) --[PSYoungGen: 4186K->4186K(5632K)] 17012K->17012K(19456K), 0.0007192 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 4186K->0K(5632K)] [ParOldGen: 12826K->538K(11264K)] 17012K->538K(16896K), [Metaspace: 2658K->2658K(1056768K)], 0.0048889 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
null null null null null null null null null null null null null null [B@7d4991ad 
循环结束:15
Heap
 PSYoungGen      total 5632K, used 4417K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
  eden space 4608K, 95% used [0x00000000ff980000,0x00000000ffdd06e8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 11264K, used 538K [0x00000000fec00000, 0x00000000ff700000, 0x00000000ff980000)
  object space 11264K, 4% used [0x00000000fec00000,0x00000000fec869f0,0x00000000ff700000)
 Metaspace       used 2666K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 283K, capacity 386K, committed 512K, reserved 1048576K

2. 垃圾回收算法

2.1 标记清除

定义: Mark Sweep

  • 优点:速度较快
  • 会造成内存碎片

在这里插入图片描述

2.2 标记整理

定义:Mark Compact

  • 速度慢
  • 优点:没有内存碎片

在这里插入图片描述

2.3 复制

定义:Copy

  • 不会有内存碎片
  • 需要占用双倍内存空间

在这里插入图片描述

复制完成后交换From和To

3. 分代垃圾回收

在这里插入图片描述

  • 对象首先分配在伊甸园区域
  • 新生代空间不足时,触发 minor gc,伊甸园和 from 存活的对象使用 copy 复制到 to 中,存活的对象年龄加 1 并且交换 from 和 to
  • minor gc 会引发 stop the world,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行
  • 当对象寿命超过阈值时,会晋升至老年代,最大寿命是 15 (4bit)
  • 老年代空间不足,会先尝试触发 minor gc,如果之后空间仍不足,那么触发 full gc,STW(stop the world)的时间更长

相关 VM 参数

含义参数
堆初始大小-Xms
堆最大大小-Xmx-XX:MaxHeapSize=size
新生代大小-Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size )
幸存区比例(动态)-XX:InitialSurvivorRatio=ratio-XX:+UseAdaptiveSizePolicy
幸存区比例-XX:SurvivorRatio=ratio
晋升阈值-XX:MaxTenuringThreshold=threshold
晋升详情-XX:+PrintTenuringDistribution
GC详情-XX:+PrintGCDetails -verbose:gc
FullGC 前 MinorGC-XX:+ScavengeBeforeFullGC
  • 新生代空间不够时,会直接放到老年代
  • 线程内的内存溢出不会影响到主线程的运行
package top.onefine.jvm.test.t2;

import java.util.ArrayList;

/**
 * 演示内存的分配策略
 */
public class Demo2_1 {
    private static final int _512KB = 512 * 1024;
    private static final int _1MB = 1024 * 1024;
    private static final int _6MB = 6 * 1024 * 1024;
    private static final int _7MB = 7 * 1024 * 1024;
    private static final int _8MB = 8 * 1024 * 1024;

    // -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:-ScavengeBeforeFullGC
    // -XX:+UseSerialGC 是一种垃圾回收器
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            ArrayList<byte[]> list = new ArrayList<>();
            list.add(new byte[_8MB]);
            list.add(new byte[_8MB]);
        }).start();

        System.out.println("sleep....");
        Thread.sleep(2000L);
        System.out.println("main end.");
    }
}

JVM参数:
在这里插入图片描述

执行:

sleep....
[GC (Allocation Failure) [DefNew: 2790K->745K(9216K), 0.0012293 secs][Tenured: 8192K->8935K(10240K), 0.0017947 secs] 10982K->8935K(19456K), [Metaspace: 3585K->3585K(1056768K)], 0.0030957 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [Tenured: 8935K->8885K(10240K), 0.0015058 secs] 8935K->8885K(19456K), [Metaspace: 3585K->3585K(1056768K)], 0.0015260 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
	at top.onefine.jvm.test.t2.Demo2_1.lambda$main$0(Demo2_1.java:21)
	at top.onefine.jvm.test.t2.Demo2_1$$Lambda$1/531885035.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)
main end.
Heap
 def new generation   total 9216K, used 382K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,   4% used [0x00000000fec00000, 0x00000000fec5fac8, 0x00000000ff400000)
  from space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 8885K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  86% used [0x00000000ff600000, 0x00000000ffead5e0, 0x00000000ffead600, 0x0000000100000000)
 Metaspace       used 3610K, capacity 4622K, committed 4864K, reserved 1056768K
  class space    used 394K, capacity 454K, committed 512K, reserved 1048576K

4. 垃圾回收器

  1. 串行
  • 单线程
  • 堆内存较小,适合个人电脑
  1. 吞吐量优先
  • 多线程
  • 堆内存较大,多核 cpu
  • 单位时间内,STW 的时间最短 0.2 0.2 = 0.4,垃圾回收时间占比最低,这样就称吞吐量高
  1. 响应时间优先
  • 多线程
  • 堆内存较大,多核 cpu
  • 尽可能让单次 STW 的时间最短 0.1 0.1 0.1 0.1 0.1 = 0.

4.1 串行

-XX:+UseSerialGC = Serial + SerialOld

在这里插入图片描述

  • Serial:新生代,采用复制算法
  • SerialOld:老年代,采用标记+整理算法

4.2 吞吐量优先

-XX:+UseParallelGC ~ -XX:+UseParallelOldGC

-XX:+UseAdaptiveSizePolicy

-XX:GCTimeRatio=ratio

-XX:MaxGCPauseMillis=ms

-XX:ParallelGCThreads=n

在这里插入图片描述

4.3 响应时间优先(CMS)

-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld

-XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads

-XX:CMSInitiatingOccupancyFraction=percent

-XX:+CMSScavengeBeforeRemark

在这里插入图片描述

4.4 G1

定义:Garbage First

  • 2004 论文发布
  • 2009 JDK 6u14 体验
  • 2012 JDK 7u4 官方支持
  • 2017 JDK 9 默认

适用场景

  • 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200 ms
  • 超大堆内存,会将堆划分为多个大小相等的 Region
  • 整体上是标记+整理算法,两个区域之间是复制算法

相关 JVM 参数

-XX:+UseG1GC
-XX:G1HeapRegionSize=size
-XX:MaxGCPauseMillis=time

1) G1 垃圾回收阶段

在这里插入图片描述

2) Young Collection

  • 会 STW

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3) Young Collection + CM

  • 在 Young GC 时会进行 GC Root 的初始标记
  • 老年代占用堆空间比例达到阈值时,进行并发标记(不会 STW),由下面的 JVM 参数决定
    -XX:InitiatingHeapOccupancyPercent=percent (默认45%)

在这里插入图片描述

4) Mixed Collection

会对 E、S、O 进行全面垃圾回收

  • 最终标记(Remark)会 STW
  • 拷贝存活(Evacuation)会 STW

-XX:MaxGCPauseMillis=ms

在这里插入图片描述

5) Full GC

  • SerialGC
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - full gc
  • ParallelGC
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - full gc
  • CMS
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足
  • G1
    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足

6) Young Collection 跨代引用

  • 新生代回收的跨代引用(老年代引用新生代)问题
    在这里插入图片描述

  • 卡表与 Remembered Set

  • 在引用变更时通过 post-write barrier+ dirty card queue

  • concurrent refinement threads 更新 Remembered Set

在这里插入图片描述

7) Remark

  • pre-write barrier + satb_mark_queue

在这里插入图片描述

8) JDK 8u20 字符串去重

  • 优点:节省大量内存
  • 缺点:略微多占用了 cpu 时间,新生代回收时间略微增加

-XX:+UseStringDeduplication

String s1 = new String("hello"); // char[]{'h','e','l','l','o'}
String s2 = new String("hello"); // char[]{'h','e','l','l','o'}
  • 将所有新分配的字符串放入一个队列
  • 当新生代回收时,G1并发检查是否有字符串重复
  • 如果它们值一样,让它们引用同一个 char[]
  • 注意,与 String.intern() 不一样
    • String.intern() 关注的是字符串对象
    • 而字符串去重关注的是 char[]
    • 在 JVM 内部,使用了不同的字符串表

9) JDK 8u40 并发标记类卸载

所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再使用,则卸载它所加载的所有类

-XX:+ClassUnloadingWithConcurrentMark 默认启用

10) JDK 8u60 回收巨型对象

  • 一个对象大于 region 的一半时,称之为巨型对象
  • G1 不会对巨型对象进行拷贝
  • 回收时被优先考虑
  • G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为 0 的巨型对象就可以在新生代垃圾回收时处理掉

11) JDK 9 并发标记起始时间的调整

  • 并发标记必须在堆空间占满前完成,否则退化为 FullGC
  • JDK 9 之前需要使用 -XX:InitiatingHeapOccupancyPercent
  • JDK 9 可以动态调整
    • -XX:InitiatingHeapOccupancyPercent 用来设置初始值
    • 进行数据采样并动态调整
    • 总会添加一个安全的空档空间

12) JDK 9 更高效的回收

5. 垃圾回收调优

预备知识

  • 掌握 GC 相关的 VM 参数,会基本的空间调整
  • 掌握相关工具
  • 明白一点:调优跟应用、环境有关,没有放之四海而皆准的法则

查看虚拟机运行参数:

C:\Users\onefine>java -XX:+PrintFlagsFinal -version | findstr "GC"
    uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
    uintx AutoGCSelectPauseMillis                   = 5000                                {product}
     bool BindGCTaskThreadsToCPUs                   = false                               {product}
    uintx CMSFullGCsBeforeCompaction                = 0                                   {product}
    uintx ConcGCThreads                             = 0                                   {product}
     bool DisableExplicitGC                         = false                               {product}
     bool ExplicitGCInvokesConcurrent               = false                               {product}
     bool ExplicitGCInvokesConcurrentAndUnloadsClasses  = false                               {product}
    uintx G1MixedGCCountTarget                      = 8                                   {product}
    uintx GCDrainStackTargetSize                    = 64                                  {product}
    uintx GCHeapFreeLimit                           = 2                                   {product}
    uintx GCLockerEdenExpansionPercent              = 5                                   {product}
     bool GCLockerInvokesConcurrent                 = false                               {product}
    uintx GCLogFileSize                             = 8192                                {product}
    uintx GCPauseIntervalMillis                     = 0                                   {product}
    uintx GCTaskTimeStampEntries                    = 200                                 {product}
    uintx GCTimeLimit                               = 98                                  {product}
    uintx GCTimeRatio                               = 99                                  {product}
     bool HeapDumpAfterFullGC                       = false                               {manageable}
     bool HeapDumpBeforeFullGC                      = false                               {manageable}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx MaxGCMinorPauseMillis                     = 4294967295                          {product}
    uintx MaxGCPauseMillis                          = 4294967295                          {product}
    uintx NumberOfGCLogFiles                        = 0                                   {product}
     intx ParGCArrayScanChunk                       = 50                                  {product}
    uintx ParGCDesiredObjsFromOverflowList          = 20                                  {product}
     bool ParGCTrimOverflow                         = true                                {product}
     bool ParGCUseLocalOverflow                     = false                               {product}
    uintx ParallelGCBufferWastePct                  = 10                                  {product}
    uintx ParallelGCThreads                         = 13                                  {product}
     bool ParallelGCVerbose                         = false                               {product}
     bool PrintClassHistogramAfterFullGC            = false                               {manageable}
     bool PrintClassHistogramBeforeFullGC           = false                               {manageable}
     bool PrintGC                                   = false                               {manageable}
     bool PrintGCApplicationConcurrentTime          = false                               {product}
     bool PrintGCApplicationStoppedTime             = false                               {product}
     bool PrintGCCause                              = true                                {product}
     bool PrintGCDateStamps                         = false                               {manageable}
     bool PrintGCDetails                            = false                               {manageable}
     bool PrintGCID                                 = false                               {manageable}
     bool PrintGCTaskTimeStamps                     = false                               {product}
     bool PrintGCTimeStamps                         = false                               {manageable}
     bool PrintHeapAtGC                             = false                               {product rw}
     bool PrintHeapAtGCExtended                     = false                               {product rw}
     bool PrintJNIGCStalls                          = false                               {product}
     bool PrintParallelOldGCPhaseTimes              = false                               {product}
     bool PrintReferenceGC                          = false                               {product}
     bool ScavengeBeforeFullGC                      = true                                {product}
     bool TraceDynamicGCThreads                     = false                               {product}
     bool TraceParallelOldGCTasks                   = false                               {product}
     bool UseAdaptiveGCBoundary                     = false                               {product}
     bool UseAdaptiveSizeDecayMajorGCCost           = true                                {product}
     bool UseAdaptiveSizePolicyWithSystemGC         = false                               {product}
     bool UseAutoGCSelectPolicy                     = false                               {product}
     bool UseConcMarkSweepGC                        = false                               {product}
     bool UseDynamicNumberOfGCThreads               = false                               {product}
     bool UseG1GC                                   = false                               {product}
     bool UseGCLogFileRotation                      = false                               {product}
     bool UseGCOverheadLimit                        = true                                {product}
     bool UseGCTaskAffinity                         = false                               {product}
     bool UseMaximumCompactionOnSystemGC            = true                                {product}
     bool UseParNewGC                               = false                               {product}
     bool UseParallelGC                            := true                                {product}
     bool UseParallelOldGC                          = true                                {product}
     bool UseSerialGC                               = false                               {product}
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

C:\Users\onefine>

5.1 调优领域

  • 内存
  • 锁竞争
  • cpu 占用
  • io

5.2 确定目标

  • 【低延迟】还是【高吞吐量】,选择合适的回收器
  • CMS,G1,ZGC:低延迟
  • ParallelGC :高吞吐量

除HotSpot外,其他虚拟机:

  • Zing

5.3 最快的 GC

答案是不发生 GC

  • 查看 FullGC 前后的内存占用,考虑下面几个问题
    • 数据是不是太多?
      • esultSet = statement.executeQuery(“select * from 大表 limit n”)
    • 数据表示是否太臃肿?
      • 对象图
      • 对象大小 16 Integer 24 int 4
    • 是否存在内存泄漏?
      • static Map map =
      • 第三方缓存实现

5.4 新生代调优

  • 新生代的特点

    • 所有的 new 操作的内存分配非常廉价
      • TLAB thread-local allocation buffer
    • 死亡对象的回收代价是零
    • 大部分对象用过即死
    • Minor GC 的时间远远低于 Full GC
  • 越大越好吗?

-Xmn
Sets the initial and maximum size (in bytes) of the heap for the young generation (nursery). GC is performed in this region more often than in other regions. If the size for the young generation is too small, then a lot of minor garbage collections are performed. If the size is too large, then only full garbage collections are performed, which can take a long time to complete. Oracle recommends that you keep the size for the young generation greater than 25% and less than 50% of the overall heap size.

  • 新生代能容纳所有【并发量 * (请求-响应)】的数据
  • 幸存区大到能保留【当前活跃对象+需要晋升对象】
  • 晋升阈值配置得当,让长时间存活对象尽快晋升
    -XX:MaxTenuringThreshold=threshold
    -XX:+PrintTenuringDistribution
Desired survivor size 48286924 bytes, new threshold 10 (max 10)
- age 1: 28992024 bytes, 28992024 total
- age 2: 1366864 bytes, 30358888 total
- age 3: 1425912 bytes, 31784800 total
...

5.5 老年代调优

以 CMS 为例

  • CMS 的老年代内存越大越好
  • 先尝试不做调优,如果没有 Full GC 那么已经很OK,先尝试调优新生代
  • 观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
    • -XX:CMSInitiatingOccupancyFraction=percent

5.6 案例

  • 案例1 Full GC 和 Minor GC频繁
  • 案例 2 请求高峰期发生 Full GC,单次暂停时间特别长 (CMS)
  • 案例 3 老年代充裕情况下,发生 Full GC (CMS jdk1.7)
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 09:51:10  更:2021-09-18 09:53:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 4:20:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计