• JVM调优入门


    JVM调优入门

    0、序

    jdk1.8,hotspot虚拟机

    官方参数文档链接

    JDK8官方参数文档连接

    JDK7官方参数文档连接

    1、参数设置

    所有配置参数笔者默认为大小写敏感,在使用时一定校验是否有符号、拼写、大小写错误

    1.1 参数分类

    • 标准参数(-):所有的JVM实现都必须实现这些参数的功能,而且向上兼容;

    • 非标准参数(-X):默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向上兼容;

    • 非Stable参数(-XX):此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用(但是,这些参数往往是非常有用的);

    1.2 标准参数

    在控制台输入java 获取支持的标准参数

    1.2.1 -client

    设置jvm使用client模式,启动速度快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或者PC应用开发和调试。

    1.2.2 -server

    设置jvm使server模式,启动速度比较慢,运行时性能和内存管理效率很高,适用于生产环境。在具有64位能力的jdk环境下将默认启用该模式。

    1.2.3 -verbose

    • -verbose:class 输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进 行诊断。

    • -verbose:gc 输出每次GC的相关情况,后面会有更详细的介绍。

    • -verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用错误信息。

    1.2.4 -D<名称>=<值>

    设置系统属性运行在此jvm之上的应用程序可用System.getProperty("property")得到value的值。如果value中有空格,则需要用双引号将该值括起来。 如:-Dname="space string" 该参数通常用于设置系统级全局变量值,如配置文件路径,以便该属性在程序中任何地方都可访问。

    1.2.5 -X

    在控制台输入,输出非标准的参数列表及其描述。

    java -X

    1.3 非标准参数

    非标准参数,是在标准参数的基础上进行扩展的参数,不同类型JVM上参数也有所不同。图仅作示例,全部非标准参数内容请自行查阅。

     

     

     

    1.3.1 -Xmx

    JVM最大允许分配的堆内存;默认为物理内存的1/4或者1G,最小为2M;可以指定单位,比如k、m,若不指定,则默认为字节。

    -Xmx1024m //  == -Xmx1g,最大堆内存为1g

    1.3.2 -Xms

    JVM初始分配的堆内存,默认为物理内存的1/64,最小为1M;单位与-Xms一致,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存;

    1.3.3 -Xmn

    年轻代内存大小(Eden+S0+S1)

    1.3.4 -Xss

    设置每个线程的栈大小,一般为512k/1M;

    1.3.5 -Xloggc:file

    与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。若与verbose命令同时出现,以-Xloggc为准。

    -Xloggc:$CATALINA_BASE/logs/gc.log

    1.4 非Stable参数

    以-XX作为前缀的非Stable参数列表在JVM中可能是不健壮的,后续可能会在没有通知的情况下就直接取消了,但这些参数中的确有很多是对我们很有用的。

    使用如下命令可以将支持的非Stable参数导出至文本:

    java -XX:+PrintFlagsFinal > -XXCommandText.txt

    在Hotspot中主要的参数可以大致分为3类:

    • 性能参数( Performance Options):用于JVM的性能调优和内存分配控制,如初始化内存大小的设置;

    • 行为参数(Behavioral Options):用于改变JVM的基础行为,如GC的方式和算法的选择;

    • 调试参数(Debugging Options):用于监控、打印、输出等jvm参数,用于显示jvm更加详细的信息;

    使用方法有4种:

    • -XX: + <option> 启用选项

    • -XX: - <option> 不启用选项

    • -XX:<option>=<number> 给选项设置一个数字类型值,可跟单位

      如:-XX:NewSize=512M

    • -XX:<option>=<string> 给选项设置一个字符串值

      如:-XX:HeapDumpPath=./dump.core

    1.4.1 性能参数

    • -XX:NewRatio=4:设置年轻代与年老代的比值为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5,常用值为[2](默认值)、3、4

    • -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的比值为4,则S0+S1:Eden 的比值为1+1 : 4,一个Survivor区占整个年轻代的1/6,常用值4、[8]

    • -XX:MetaspaceSize=256m、-XX:MaxMetaspaceSize=256M :设置元空间默认大小、最大值(jdk1.7方法区、持久代 -XX:MaxPermSize=16M)

    • -XX:MaxTenuringThreshold= 0:设置分代年龄,默认为15,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。

    • -XX:ParallelGCThreads=8:并发垃圾收集时开启线程数量

    • -XX:ConcGCThreads=0:并行垃圾收集时开启的线程数量

    1.4.2 行为参数

    • -XX:-DisableExplicitGC:禁止调用System.gc();但jvm的gc仍然有效

    • -XX:+ScavengeBeforeFullGC:Minor GC优先于Full GC执行

    • -XX:+UseConcMarkSweepGC :ParNewGC + CMS GC

      若出现Concurrent Mode Failure则使用 SerialOld GC替换CMS

    • -XX:+CMSParallelRemarkEnabled:搭配CMS使用,降低标记停顿

    • -XX:+UseSerialGC:Client模式下默认组合

      SerialGC + SerialOld GC 组合

    • -XX:+UseParNewGC:ParNewGC + SerialOld GC 组合

    • -XX:+UseParallelGC:Server模式下默认组合

      Parallel Scavenge GC + SerialOld GC 组合

    • -XX:+UseParallelOldGC:Parallel Scavenge GC + ParallelOldGC 组合

    • -XX:LargePageSizeInBytes=128M:内存页的大小

    参考文献:《深入理解JAVA虚拟机》

    1.4.3 调试参数

    以下命令须配合-verbose:gc一起使用

    • -XX:+PrintGCDetails:打印GC详情

    • -XX:+PrintGCTimeStamps:打印发生fullgc的时间戳

    • -XX:-HeapDumpOnOutOfMemoryError:当首次遭遇OOM时导出此时堆中相关信息

    • -XX:+PrintGCApplicationStoppedTime:打印GC时SWT的时间

    • -XX:PrintHeapAtGC: 打印GC前后详细的堆栈信息

    2、收集器套餐推荐

    • 一般来说,Java桌面应用,建议采用-client模式套餐即Serial+Serial Old收集器组合:-XX:+UseSerialGC

    • 在开发/测试环境,可以采用-server下默认参数即

      Parallel Scavenge + Serial Old收集器组合:-XX:+UseParallelGC

    • 在线上运算优先的环境,建议采用Parallel Scavenge+Serial Old收集器组合:-XX:+UseParallelGC

    • 在线上服务响应优先的环境,建议采用ParNew+CMS+Serial Old收集器组合:-XX:+UseConcMarkSweepGC

    3、内存分配

    • 堆大小设置Xms 和 Xmx设置为老年代存活对象所占内存的3-4倍,即FullGC之后的老年代内存占用的3-4倍

    • 永久代 PermSize和MaxPermSize元空间Metaspacesize及MaxMetaspacesize设置为老年代存活对象的1.2-1.5倍。

    • 年轻代Xmn的设置为老年代存活对象的1-1.5倍。

    • 老年代的内存大小设置为老年代存活对象的2-3倍。

    如:当系统稳定运行一段时间后,老年代所占内存为64M则有如下性能参数设置:

    -Xms256M
    -Xmx256M
    -Xmn86M
    -XX:MetaspaceSize=96M 
    -XX:MaxMetaspaceSize=96M 
    //年轻代:老年代 = 1:2

    4、监控工具

    4.1 命令行工具

    4.1.1 jps命令

    jps命令用于查询正在运行的JVM进程,命令格式为:

    jps [option] [hostid]

    常用的参数为:

    • -q:只输出VM ID,省略主类的名称

    • -m:输出虚拟机进程启动时传给主类main()函数的参数

    • -l:输出主类的全类名,如果进程执行的是Jar包,输出Jar路径

    • -v:输出虚拟机进程启动时JVM参数

    4.1.2 jstat命令

    jstat(Java Virtual Machine statistics monitoring tool)JDK自带的一个轻量级工具, 利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。

    jstat有如下选项:

    • -class:监视类装载、卸载数量、总空间及类装载所耗费的时间

    • -gc:监听Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量,以用空间、GC时间合计等信息

    • -gccapacity:监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大和最小空间

    • -gcutil:监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比

    • -gccause:与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因

    • -gcnew:监视新生代GC状况

    • -gcnewcapacity:监视内同与-gcnew基本相同,输出主要关注使用到的最大和最小空间

    • -gcold:监视老年代GC情况

    • -gcoldcapacity:监视内同与-gcold基本相同,输出主要关注使用到的最大和最小空间

    • -gcpermcapacity:输出永久代使用到最大和最小空间

    • -compiler:输出JIT编译器编译过的方法、耗时等信息

    • -printcompilation:输出已经被JIT编译的方法

    示例:

    监控GC情况,被监控VMID为12636,每1000ms收集一次GC状态,共收集5次

     

    • S0C:S0区容量(S1区相同,略)

    • S0U:S0区已使用

    • EC:E区容量

    • EU:E区已使用

    • OC:老年代容量

    • OU:老年代已使用

    • MC:MetaSpace容量

    • MU:MetaSpace区已使用

    • CCSC:当前压缩类空间大小

    • CCSU:当前压缩类空间已使用大小

    • YGC:Young GC(Minor GC)次数

    • YGCT:Young GC总耗时

    • FGC:Full GC次数

    • FGCT:Full GC总耗时

    • GCT:GC总耗时

    4.2 图形化工具

    4.2.1 JVisualVM

    VisualVM是一个集成多个JDK命令行工具的可视化工具,它具备了插件扩展功能的特性,通过插件的扩展,可用于显示虚拟机进程及进程的配置和环境信息(jps,jinfo),监视应用程序的CPU、GC、堆、方法区及线程的信息(jstat、jstack)等。

    JVisualVM插件下载链接

    • 使用方法:控制台键入 jvisualvm打开工具

    • 插件安装:下载对应jdk版本的visual gc插件,点工具-插件-已下载-打开安装。

    • 启用监控:右键点击本地VM进程-打开-Visual GC 观察JVM内存运行情况

    5、调优论述

    5.1 目的

    • 将转移到老年代的对象数量降低到最小;

    • 减少full GC的执行时间 — 减少业务阻塞;

    5.2 原则

    • 多数的Java应用不需要在服务器上进行GC优化;

    • 多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;

    • 在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);

    • 减少创建对象的数量;

    • 减少使用全局变量和大对象;

    • GC优化是到最后不得已才采用的手段;

    • 在实际使用中,分析GC情况优化代码比优化GC参数要多得多;

    5.3 调优方法

    • 方法1:稳定运行系统一段时间,使用监控工具查看当前JVM内存性能及gc情况,按照老年代占用内存比例,调整各内存性能参数。适合并发低、业务稳定应用。

    • 方法2:分析估算单业务线完整生命周期占用的内存(主要是新生代)情况,并结合当前服务器可以稳定处理的峰值并发量,合理分配新生代内存容量及配比。适合业务处理时间短,高并发的应用。

    • 方法3:选择适合的垃圾收集器套餐,系统默认参数足够应对绝大多数应用场景。

    5.4 示例

    仅供参考,先测后用

    -Xmx300m                //最大堆大小             
    -Xms300m                //最小堆大小
    -Xmn100m                //新生代大小                      
    -XX:SurvivorRatio=8     //Eden:Survivor
    -XX:+UseConcMarkSweepGC //使用ParNew+CMS+Serial Old收集器组合
    -XX:MaxTenuringThreshold=15 //分代年龄,15岁以后进入老年代
    -XX:ParallelGCThreads=8 //CMS并行线程数
    -XX:ConcGCThreads=8     //ParNew并发线程数
    -XX:+DisableExplicitGC  //禁用System.gc()
    -XX:+HeapDumpOnOutOfMemoryError //导出堆OOM的异常信息
    -XX:HeapDumpPath=d:/a.dump      //导出路径        
    -XX:+PrintGCDetails             //打印GC详情        
    -XX:+PrintGCTimeStamps          //打印时间戳
    -XX:+PrintHeapAtGC              //打印GC前后堆的情况
    -XX:+TraceClassLoading          //显示类加载信息    

    Surprise

    当你在一家中小型公司,可能根本用不上JVM调优的相关内容,但这并不影响面试的时候被问,这就很无奈~多掌握一些总没什么错,99.9%的bug都是代码写的有问题,切勿让JVM背锅—至向上的自己...JVM入门,完结撒花~

  • 相关阅读:
    c++ 视频和教程下载站点
    SQL超时解决方法
    初学者必备:C++经典入门详细教程
    人生致命的八个经典问题
    字长与字节
    typedef用法(三)
    遍历搜索注册表
    数据库连接字符串大全 之 SQL服务器篇
    十五个步骤收获学习的习惯
    谈基于.net平台windows开发中的模式窗体.NET教程,.NET Framework
  • 原文地址:https://www.cnblogs.com/lijizhi/p/12434707.html
Copyright © 2020-2023  润新知