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


    JVM系列整体栏目


    内容链接地址
    【一】初识虚拟机与java虚拟机https://blog.csdn.net/zhenghuishengq/article/details/129544460
    【二】jvm的类加载子系统以及jclasslib的基本使用https://blog.csdn.net/zhenghuishengq/article/details/129610963
    【三】运行时私有区域之虚拟机栈、程序计数器、本地方法栈https://blog.csdn.net/zhenghuishengq/article/details/129684076
    【四】运行时数据区共享区域之堆、逃逸分析https://blog.csdn.net/zhenghuishengq/article/details/129796509
    【五】运行时数据区共享区域之方法区、常量池https://blog.csdn.net/zhenghuishengq/article/details/129958466
    【六】对象实例化、内存布局和访问定位https://blog.csdn.net/zhenghuishengq/article/details/130057210
    【七】执行引擎,解释器、JIT即时编译器https://blog.csdn.net/zhenghuishengq/article/details/130088553
    【八】精通String字符串底层机制https://blog.csdn.net/zhenghuishengq/article/details/130154453
    【九】垃圾回收底层原理和算法以及JProfiler的基本使用https://blog.csdn.net/zhenghuishengq/article/details/130261481
    【十】垃圾回收器的种类以及内部的执行原理https://blog.csdn.net/zhenghuishengq/article/details/130261481
    【十一】jvm性能调优篇之命令行工具的基本使用https://blog.csdn.net/zhenghuishengq/article/details/130641456
    【十二】jvm性能调优篇之GUI工具的基本使用https://blog.csdn.net/zhenghuishengq/article/details/130745931
    【十三】jvm性能调优篇之参数设置以及日志分析https://blog.csdn.net/zhenghuishengq/article/details/130802703

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

    1,JVM的参数设置

    1.1,标准参数选项

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

    java -help
    
    • 1

    1.2,-X参数选项

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

    java -X
    
    • 1

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

    -Xms10m -Xmx10m -Xss10m
    
    • 1

    1.3,-XX参数类型

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

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

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

    非boolean类型的如下

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

    2,添加JVM参数

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

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

    3,常用的JVM的参数选项

    打印的相关参数有

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

    栈的相关参数有

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

    堆内存的相关参数

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

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

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

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

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

    OutofMemory相关参数

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

    垃圾收集相关选项

    -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          设置并发标记的线程数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    GC日志相关选项

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

    其他参数

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

    也可以通过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());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    其打印结果如下

    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============================ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    二,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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    [PSYoungGen5986K -> 696K(8704K)] 5986K -> 704K(9216K)
    
    • 1

    GC失败的场景

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xblxYu63-1684723839903)(img/1684721455060.png)]

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

    在这里插入图片描述

    在all Thread这里,可以发现这现线程的状态,正处于阻塞状态
    在这里插入图片描述
    总而言之,这款工具还是挺好使用的

  • 相关阅读:
    【博客450】OpenFlow学习
    【vue】vue实现海康ws协议的实时监控播放:
    Nginx学习笔记
    品牌方发行NFT时,应如何考量实用性?
    puzzle(103.1)网格图一笔画
    【Qt之Model/View】编程
    《深度学习进阶 自然语言处理》第六章:LSTM介绍
    JAVA开放式体育社区及论坛计算机毕业设计Mybatis+系统+数据库+调试部署
    basic_vsr 代码介绍
    windows平台FairMOT的实现
  • 原文地址:https://blog.csdn.net/zhenghuishengq/article/details/130802703