【JVM实战】JVM参数调优

JVM参数调优

一、调优基本概念

在调整性能时,JM有三个组件

  1. 堆大小调整
  2. 垃圾收集器调整
  3. JIT编译器调整

大多数调优选项都与调整堆大小和选择的垃圾收集器有关

同样,JIT编译器对性能也有很大影响,但是这个对程序员自身要求非常高。

通常,在调优Java应用程序时,重点是以下两个主要目标之一:

  • 响应性:应用程序或系统对请求的数据进行响应的速度,对于专注于响应性的应用程序,长的暂停时间是不可接受的,重点是在短时间内做出回应。
  • 吞吐量:侧重于在特定时间段内最大化应用程序的工作量,对于专注于吞吐量的应用程序,高暂停时间是可接受的。

一般而言,系统瓶颈核心还是在应用代码,一般情况下无需过多调优,而且JVM本身在不断优化的过程。

二、常用JVM参数

文章围绕Java8,下面的一些参数,在JDK9之后就被淘汰了,加红进行了凸显。

参数 说明
-XX:+AlwaysPreTouch JVM启动时分配内存,非使用时再分配
-XX:ErrorFile= filename 崩溃日志
-XX:+TraceClassLoading 跟踪类加载信息
-XX:+PrintClassHistogram 按下Ctr+ Break后,打印类的信息
-Xmx -Xms 最大堆和最小堆
-xx:permSize, -xx:metaspaceSize 永久代/元数据空间
-XX:+HeapDumpOnOutOfMemoryError 0OM时导出堆到文件
-XX:+HeapDumpPath OOM时堆导出的路径
-XX:+OnOutOfMemoryError JVM启动时分配内存,非使用时再分配在OOM时,执行一个脚本
java-XX:+PrintFlagsFinal -version  打印所有的-XX参数和默认值

通用GC参数

参数 说明
-XX:ParallelGCThread 并行GC线程数量
-XX:ConcGCThreads 并发GC线程数量
-XX:MaxGCPauseMillis 最大停顿时间,单位毫秒。GC尽力保证回收时间不超过设定值
-XX:GCTimeRatio 0-100的取值范围,表示垃圾收集时间占总时间的比,默认99,即最大允许1%时间进行GC
-XX. SurvivorRatio 设置Eden区大小和 Survivor区大小的比例, 8表示两个 Survivor:Eden=2:8,即一个 Survivor占年轻代的1/10
-XX:NewRatio 新生代和老年代的比,4表示新生代老年代=1:4,即年轻代占堆的1/5
-verbose:gc, -XX;+printGC 打印GC的简要信息
-XX:+PrintGCDetails 打印GC详细信息
-XX:+PrintGCTimeStamps 打印CG发生的时间戳
-Xloggc:log/gc.log 指定 GC log的位置,以文件输出
-XX:ParallelGCThread 每次一次GC后,都打印堆信息

三、GC调优思路

首先准备环境

创建一个springboot的空项目,在启动类部分添加一下代码,打包,放在阿里云服务器上运行。

扫描二维码关注公众号,回复: 10399908 查看本文章

测试环境:JVM配置为1核2G,JAVA8,固定设置堆大小 1G

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        // 每333毫秒创建150线程,每个线程创建一个512kb的对象,最多一秒同时存在450线程,占用内存225m,查看6C的情况
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
            new Thread(() -> {
                for (int i = 0; i < 150; i++) {
                    try {
                        //  不干活,专门创建512kb的小对象
                        byte[] temp = new byte[1024 * 512];
                        Thread.sleep(new Random().nextInt(100)); // 随机睡眠200毫秒秒以内
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }, 1000, 333, TimeUnit.MILLISECONDS);
    }
}

在运行之前要记得指定一下堆的大小

java -Xmx1024m -jar xxx.jar

启动是正常的
在这里插入图片描述
上面已经能看到端口号了,但是我们这里用jcmd象征的看一下
在这里插入图片描述
我们看一下堆的使用情况
在这里插入图片描述
里面的数据都是动态的。

我们看一下调优的思路

  1. 分析场景。例如:启动速度慢;偶尔出现响应慢于平均水平或者出现卡顿
  2. 确定目标。内存占用、低延时、吞吐量
  3. 收集日志。通过参数配置收集GC日志;通过JDK工具查看GC状态(例如jstat 实时查看)
  4. 分析日志。使用工具辅助分析日志,查看GC次数,GC时间(事后分析)
  5. 调整参数。切换垃圾收集器或者调整垃圾收集器参数

前两点的话,要和具体场景结合起来。文章主要展示整个过程该怎么走(相当于工具说明书),具体问题要具体分析。

java -Xmx1024m -Xloggc:/opt/gc.log -jar xxx.jar

我们这里添加了日志的收集
在这里插入图片描述
我们去对应目录找一下日志,里面的参数我们都介绍过,这个不难看懂。
在这里插入图片描述
但是文件内容是非常非常多的,这样一点点的看可能有点困难,我们一边把文件下载下来,用GCViewer这个开源的工具来做这件事情。

GCViewer工具,辅助分析GC日志文件 https://github.com/chewiebug/GCViewer
在这里插入图片描述
打开下载到本地的gc.log文件
在这里插入图片描述
再看右下角的信息,主要是一些汇总信息。各种数据的分析,比如平均,最大,最小等。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
至于首页的图形,怎么看,可以直接参考文档:https://github.com/chewiebug/GCViewer

红线意思是什么等等 都写的很详细。

在这里插入图片描述
下面看一下jstat 动态监控GC统计信息,采用的格式是间隔1000毫秒统计一次,每10行数据后输出列标题

jstat -gc -h10 $(jcmd | grep "demo-0.0.1-SNAPSHOT.jar" | awk '{print $1}') 1000

里面的参数,我们说过了,参考上一篇文章【JVM实战】基于JDK命令行工具的监控
在这里插入图片描述

下面看一下切换垃圾收集器或者调整垃圾收集器参数相关信息:

垃圾收集器 Parallel参数调优

这是JDK默认的收集器–吞吐量优先

参数 说明
-XX:+UseParallelGC 新生代使用并行回收收集器
-XX:+Use ParalleloldGC 老年代使用并行回收收集器
-XX:ParallelGCThreads 设置用于垃圾回收的线程数
-XX:+UseAdaptiveSizePolicy 打开自适应GC策略

自适应GC策略是指自动调整分代分区的大小。UseAdaptiveSizePolicy自适应默认开启。

垃圾收集器CMS参数调优

关于CMS

  • 响应时间优先2
  • Parallel gc无法满足应用程序延迟要求时再考虑使用CMS垃圾收集器。
  • 新版建议用G1垃圾收集器

在这里插入图片描述
垃圾收集器G1参数调优

关于G1:

  • 兼顾吞吐量和响应时间
  • 超过50%的Java堆被实时数据占用。
  • 建议大堆(大小约为6GB或更大)
  • 且GC延迟要求有限的应用(稳定且可预测的暂停时间低于0.5秒)。
    在这里插入图片描述

运行时JIT编译器优化参数

JIT编译指的是字节码编译为本地代码(汇编)执行,只有热点代码才会编译为本地代码。解释器执行节约内存,反之可以使用编译执行来提升效率

在这里插入图片描述
最后由于版本不断更新,JVM参数和具体说明,建议需要时参考 oracle官网的手册。

说实话,如果没有一个具体的线上场景,很难去演示调优的过程,这里能做到的就是,给出调优的思路、相关工具的使用,以及调优用到的参数信息。

参数的调整多少都会对JVM的运行有影响,比如 Parallel参数调优中-XX:ParallelGCThreads设置线程的数量,这个在不同配置的服务器上测试得到的结果会有差别,你可以在自己服务器上试试看。

发布了205 篇原创文章 · 获赞 3768 · 访问量 59万+

猜你喜欢

转载自blog.csdn.net/qq_42322103/article/details/105192185