【jvm系列-13】jvm性能调优篇---参数设置以及日志分析

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【jvm系列-13】jvm性能调优篇---参数设置以及日志分析

一,JVM参数设置以及日志分析

1,JVM的参数设置

1.1,标准参数选项

特点就是比较稳定,后续的版本也不会变化,以-开头。可以打开cmd可执行命令,输入java -help,就可以查看对应的命令,如可以通过-server和-client模式设置是客户端模式还是服务端模式

java -help

1.2,-X参数选项

非标准化参数,功能相对稳定,后续版本可能会发生变动,以-X开头。可以输入java -X ,就可以查看到对应的命令。如可以通过这个-Xmixed来作为执行引擎的混合模式,解释器+编译器。

java -X

还有一些如设置堆的初始大小,最大大小以及设置线程的大小等

-Xms10m -Xmx10m -Xss10m

1.3,-XX参数类型

也是非标准化参数,使用的自多的参数类型,功能相对不稳定,以-XX开头,一般用于开发和调试JVM。


又可以对这些指令进行分类,分成boolean类型和非boolean类型。boolean类型的通过+、- 加或者减来启用或者禁用某个属性,因为有的指令是默认开启或者默认关闭的。如下面的一些命令:

-XX:+UseParallelGc         选择垃圾收集器为并行垃圾收集器
-XX:+UseG1GC               启用G1收集器
-XX:+UseAdaptiveSizePolicy 自动选择新生代大小和相应的s区的比例
-XX:+PrintFlagsFinal       输出所有参数的名称和默认值

非boolean类型的如下

//key/value类型
-XX:NewSize=1024M          新生代初始大小
-XX:MaxGCPauseMillis=500   设置GC停顿时间:500ms
-XX:GCTimeRatio=19         设置吞吐量
-XX:NewRatio=2             设置新生代和老年代比例

2,添加JVM参数

如在运行一个jar包,可以设置堆的大小,gc的间隔以及打印日志等


java -Xms1024m -Xmx1024m -XX:PrintGcDetails -XX:+PrintGcTimeStamps -jar xx.jar

3,常用的JVM的参数选项

打印的相关参数有

-XX:PrintFlagsFinal        表示打印出XX选项在运行时程序生效的值
-XX:PrintFlagsInitial      表示打印出XX选项的默认值
-XX:PrintVMOptions         打印JVM参数

栈的相关参数有

-Xss1m                     设置每个线程栈的大小为1m

堆内存的相关参数

-Xms1024m -Xmx1024m        设置堆的初始大小和最大大小都是1024m
-Xmn2g                     设置的是年轻代的大小
-XX:NewRatio=4             设置老年代和新生代的比例,默认为2
-XX:NewSize=1g             设置年轻代的初始大小为1g
-XX:NewMaxSize=1g          设置年轻代的最大大小为1g

在堆中还有一个重要的参数设置,这个自动选择各区比例是开启的,所有有时查看到的eden区和s区的比例有时为6:1,这个比例是动态调整的,如果想让他的值为默认值8:1,就得将这个-XX:SurvivorRatio=8 开启

-XX:SurvivorRatio=8        设置Eden区和s区的比例,默认为8
-XX:+UseAdaptiveSizePolicy 自动选择各区比例

方法区的相关参数,由于jdk8以及之后实现这个方法区的方式都是元空间,因此只谈元空间的参数设置

-XX:MetaspaceSize          初始空间
-XX:MaxMetaspaceSize=8     最大空间
-XX:+UseCompressedOops     压缩对象 指针
-XX:CompressedClassSpaceSize        设置类的元空间大小,默认是1G

OutofMemory相关参数

-XX:+HeapDumpOnOutOfMemory 表示出现OOM时,生成一个堆的dump文件
-XX:HeapDumpBeforeFullGc   表示出现这个FullGc之前,生成heap的存储文件
-XX:HeapDumpPath=<path>    指定heap转存储文件的存储路径
-XX:OnOutOfMemoryError     指定一个可行性的程序或者脚本

垃圾收集相关选项

-XX:+UseSerialGC           指定新生代和老年代使用serial回收器
-XX:+UseParNewGC           手动指定ParNewGC作为新生代的回收器
-XX:ParallelGCThreads      限制线程数量,默认开启和CPU相同的线程数
-XX:+UseParallelGC         手动指定并使用Parallel作为并行收集器
-XX:+UseParallelOldGC      手动指定老年代都是使用并行回收器
-XX:GCTimeRatio            垃圾收集时间占总时间比例
-XX:+UseAdapaiveSizePolicy 自适应调节策略
-XX:+UseConcMarkSweepGC    手动指定CMS作为垃圾回收器
-XX:ParallelCMSThreads     设置CMS的线程数量
-XX:MaxGCPauseMillis       设置期望值达到的最大GC停顿时间
-XX:ParallelGCThread       设置STW时GC线程数的值,最多设置为8
-XX:UseG1GC                手动指定使用G1收集器执行内存回收任务
-XX:G1HeapRegionSize       设置每个region的分区大小
-XX:ConcGCThreads          设置并发标记的线程数

GC日志相关选项

-verbose:gc                输出GC日志信息
-XX:+PrintGC               输出GC日志信息
-XX:+PrintGCDetails        发生垃圾回收时打印内存回收的详细信息
-XX:+PrintHeapAtGC         每一次GC前和GC后,都打印堆信息
-XX:PrintGCTimeStamps      输出gc打印时间戳信息
-Xloggc <path>             将日志文件保存到指定的path路径下

其他参数

-XX:+DisableExplicitGC      禁用虚拟机执行System.gc()
-XX:+UseCodeCacheFlushing   清理一些编译的代码
-XX:+DoEscapeAnalysis       开启逃逸分析
-XX:+UseBiasedLocking       开启偏向锁
-XX:+UseTLAB                使用TLAB,默认是打开的
-XX:TLABSize                设置TLAB的大小

也可以通过java代码来获取jvm参数

/**
 * @author zhenghuisheng
 * @date : 2023/5/19
 */
public class JvmParamTest {
    public static void main(String[] args) {
        MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
        MemoryUsage usage = memorymbean.getHeapMemoryUsage();
        System.out.println("INIT HEAP: " + usage.getInit());
        System.out.println("MAX HEAP: " + usage.getMax());
        System.out.println("USE HEAP: " + usage.getUsed());
        System.out.println("\nFull Information:");
        System.out.println("Heap Memory Usage: "
                + memorymbean.getHeapMemoryUsage());
        System.out.println("Non-Heap Memory Usage: "
                + memorymbean.getNonHeapMemoryUsage());
        List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
        System.out.println("===================java optiOns=============== ");
        System.out.println(inputArguments);
        System.out.println("=======================通过java来获取相关系统状态============================ ");
        int i = (int)Runtime.getRuntime().totalMemory()/1024;//Java 虚拟机中的内存总量,以字节为单位 
        System.out.println("总的内存量 i is "+i);
        int j = (int)Runtime.getRuntime().freeMemory()/1024;//Java 虚拟机中的空闲内存量 
        System.out.println("空闲内存量 j is "+j);
        System.out.println("最大内存量 is "+Runtime.getRuntime().maxMemory()/1024);
        System.out.println("=======================OperatingSystemMXBean============================ ");
        OperatingSystemMXBean osm = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
        //获取操作系统相关信息 
        System.out.println("osm.getArch() "+osm.getArch());
        System.out.println("osm.getAvailableProcessors() "+osm.getAvailableProcessors());
        //System.out.println("osm.getCommittedVirtualMemorySize() "+osm.getCommittedVirtualMemorySize()); 
        System.out.println("osm.getName() "+osm.getName());
        //System.out.println("osm.getProcessCpuTime() "+osm.getProcessCpuTime()); 
        System.out.println("osm.getVersion() "+osm.getVersion());
        //获取整个虚拟机内存使用情况 
        System.out.println("=======================MemoryMXBean============================ ");
        MemoryMXBean mm=(MemoryMXBean)ManagementFactory.getMemoryMXBean();
        System.out.println("getHeapMemoryUsage "+mm.getHeapMemoryUsage());
        System.out.println("getNonHeapMemoryUsage "+mm.getNonHeapMemoryUsage());
        //获取各个线程的各种状态,CPU 占用情况,以及整个系统中的线程状况 
        System.out.println("=======================ThreadMXBean============================ ");
        ThreadMXBean tm=(ThreadMXBean)ManagementFactory.getThreadMXBean();
        System.out.println("getThreadCount "+tm.getThreadCount());
        System.out.println("getPeakThreadCount "+tm.getPeakThreadCount());
        System.out.println("getCurrentThreadCpuTime "+tm.getCurrentThreadCpuTime());
        System.out.println("getDaemonThreadCount "+tm.getDaemonThreadCount());
        System.out.println("getCurrentThreadUserTime "+tm.getCurrentThreadUserTime());
        //当前编译器情况 
        System.out.println("=======================CompilatiOnMXBean============================ ");
        CompilationMXBean gm=(CompilationMXBean)ManagementFactory.getCompilationMXBean();
        System.out.println("getName "+gm.getName());
        System.out.println("getTotalCompilationTime "+gm.getTotalCompilationTime());
        //获取运行时信息 
        System.out.println("=======================RuntimeMXBean============================ ");
        RuntimeMXBean rmb=(RuntimeMXBean)ManagementFactory.getRuntimeMXBean();
        System.out.println("getClassPath "+rmb.getClassPath());
        System.out.println("getLibraryPath "+rmb.getLibraryPath());
        System.out.println("getVmVersion "+rmb.getVmVersion());
    }
}

其打印结果如下

INIT HEAP: 268435456
MAX HEAP: 3799515136
USE HEAP: 8061840
Full Information:
Heap Memory Usage: init = 268435456(262144K) used = 8061840(7872K) committed = 257425408(251392K) max = 3799515136(3710464K)
Non-Heap Memory Usage: init = 2555904(2496K) used = 5345064(5219K) committed = 8060928(7872K) max = -1(-1K)
===================java optiOns=============== 
[-javaagent:D:\idea\IntelliJ IDEA 2019.1\lib\idea_rt.jar=58982:D:\idea\IntelliJ IDEA 2019.1\bin, -Dfile.encoding=UTF-8]
=======================通过java来获取相关系统状态============================ 
总的内存量 i is 251392
空闲内存量 j is 243519
最大内存量 is 3710464
=======================OperatingSystemMXBean============================ 
osm.getArch() amd64
osm.getAvailableProcessors() 4
osm.getName() Windows 10
osm.getVersion() 10.0
=======================MemoryMXBean============================ 
getHeapMemoryUsage init = 268435456(262144K) used = 8061840(7872K) committed = 257425408(251392K) max = 3799515136(3710464K)
getNonHeapMemoryUsage init = 2555904(2496K) used = 5396384(5269K) committed = 8060928(7872K) max = -1(-1K)
=======================ThreadMXBean============================ 
getThreadCount 6
getPeakThreadCount 6
getCurrentThreadCpuTime 375000000
getDaemonThreadCount 5
getCurrentThreadUserTime 187500000
=======================CompilatiOnMXBean============================ 
getName HotSpot 64-Bit Tiered Compilers
getTotalCompilationTime 28
=======================RuntimeMXBean============================ 

二,GC日志的分析

GC按照回收区域主要分为两大类型:一种是部分收集,一种是整堆收集。 部分收集的意思就是不是完整收集整个java堆的垃圾收集,比如有新生代的Minor GC、老年代的MajorGC;整堆收集就是收集整个Java堆和方法区的垃圾收集,比如有Full GC。


触发Full GC的场景如下:老年代的空间不足、方法区的空间不足、显式调用System.GC()、Minor GC进入老年代的平均大小大于老年代的可用内存大小、大对象直接进入老年代


在GC中,一般会有三个时间:user、sys、real。


user表示的是用户态所使用的时间,这是执行此进程所使用的实际CPU时间。

sys表示的是内核态消耗的时间,即在内核系统调用或等待系统事件所使用的CPU时间

real是程序开始到结束的时间。

如下面是一段线上服务的GC日志信息

Heap:
 PSYoungGen      total 1560576K, used 202793K [0x0000000755580000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1376768K, 13% used [0x0000000755580000,0x000000076115da18,0x00000007a9600000)
  from space 183808K, 5% used [0x00000007b4c80000,0x00000007b56accb0,0x00000007c0000000)
  to   space 185344K, 0% used [0x00000007a9600000,0x00000007a9600000,0x00000007b4b00000)
 ParOldGen       total 3495424K, used 80041K [0x0000000680000000, 0x0000000755580000, 0x0000000755580000)
  object space 3495424K, 2% used [0x0000000680000000,0x0000000684e2a410,0x0000000755580000)
 Metaspace       used 93746K, capacity 98782K, committed 99608K, reserved 1136640K
  class space    used 11338K, capacity 12190K, committed 12328K, reserved 1048576K

GC日志的格式规律一般都是:GC前内存占用 —> GC后内存占用(总内存)

[PSYoungGen:5986K -> 696K(8704K)] 5986K -> 704K(9216K)

GC失败的场景

[GC (Allocation Failure) [PSYoungGen: 2240K->384K(2560K)] 4803K->2947K(9728K), 0.0006347 secs]

也可以使用一些GC工具进行日志分析,如GC EasyGC View工具等等。如下面是一个GC Easy的官网,其地址为:https://gceasy.io/,选择对应的log文件即可

在选择文件之后,就可以进入到下面的页面,从上往下滑就可以查看对应的详细信息

在all Thread这里,可以发现这现线程的状态,正处于阻塞状态

总而言之,这款工具还是挺好使用的

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
10天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
8天前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
19天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
27天前
|
Arthas 监控 数据可视化
JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货
本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。
|
1月前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
1月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
45 3
|
1月前
|
Java Android开发 开发者
【编程进阶知识】精细调控:掌握Eclipse JVM参数配置的艺术
本文详细介绍了如何在Eclipse中配置JVM参数,包括内存的初始和最大值设置。通过具体步骤和截图演示,帮助开发者掌握JVM参数的精细调控,以适应不同的开发和测试需求。
42 1
|
1月前
|
Java API 对象存储
JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
|
1月前
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
1月前
|
Java
JVM进阶调优系列(5)CMS回收器通俗演义一文讲透FullGC
本文介绍了JVM中CMS垃圾回收器对Full GC的优化,包括Stop the world的影响、Full GC触发条件、GC过程的四个阶段(初始标记、并发标记、重新标记、并发清理)及并发清理期间的Concurrent mode failure处理,并简述了GC roots的概念及其在GC中的作用。
下一篇
无影云桌面