JVM 调优篇11 调优常用jvm参数&垃圾收集器参数【经典】

目录

一 jvm配置参数

1.1 参数类型

1.2  设置打印的参数值

1.3 设置栈和堆的值 

1.4  设置方法区与直接内存的值

1.5  内存溢出的参数设置

1.6 GC日志相关的参数设置

​编辑 1.7  其它参数设置 

二 jvm调优参数设置

2.1 概述

2.2 行为参数(功能开关)

2.3 性能调优

2.4 调试参数

三  jvm的垃圾收集器参数设置

3.1 查看默认垃圾收集器

3.2 串行收集器

3.3 并行收集器

3.4.Parallel收集器

3.5.CMS收集器

3.6.G1收集器

四  案例操作

4.1 案例

五 收集器的选择原则

5.1 垃圾收集器选取原则

六  日均百万客流量的网站调优

6.1 案例


一 jvm配置参数

1.1 参数类型

1.2  设置打印的参数值

1.3 设置栈和堆的值 

1.4  设置方法区与直接内存的值

1.5  内存溢出的参数设置

1.6 GC日志相关的参数设置

1.7  其它参数设置 

二 jvm调优参数设置

2.1 概述

Java HotSpot VM中-XX:的可配置参数列表进行描述;

这些参数可以被松散的聚合成三类:

行为参数(Behavioral Options):用于改变jvm的一些基础行为;

性能调优(Performance Tuning):用于jvm的性能调优;

调试参数(Debugging Options):一般用于打开跟踪、打印、输出等jvm参数,用于显示jvm更加详细的信息;

2.2 行为参数(功能开关)

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

-XX:+MaxFDLimit 最大化文件描述符的数量限制

-XX:+ScavengeBeforeFullGC   新生代GC优先于Full GC执行

-XX:+UseGCOverheadLimit 在抛出OOM之前限制jvm耗费在GC上的时间比例

-XX:-UseConcMarkSweepGC 对老生代采用并发标记交换算法进行GC

-XX:+UseParallelGC  启用并行GC

-XX:+UseParallelOldGC   对Full GC启用并行,当-XX:-UseParallelGC启用时该项自动启用

-XX:+UseSerialGC    启用串行GC

-XX:+UseThreadPriorities    启用本地线程优先级

2.3 性能调优

-XX:LargePageSizeInBytes=4m 设置用于Java堆的大页面尺寸

-XX:MaxHeapFreeRatio=70 GC后java堆中空闲量占的最大比例

-XX:MaxNewSize=size 新生成对象能占用内存的最大值

-XX:MaxPermSize=64m 老生代对象能占用内存的最大值

-XX:MinHeapFreeRatio=40 GC后java堆中空闲量占的最小比例

-XX:NewRatio=2  新生代内存容量与老生代内存容量的比例

-XX:NewSize=2.125m  新生代对象生成时占用内存的默认值

-XX:ReservedCodeCacheSize=32m   保留代码占用的内存容量

-XX:ThreadStackSize=512 设置线程栈大小,若为0则使用系统默认值

-XX:+UseLargePages  使用大页面内存

2.4 调试参数

-XX:-CITime 打印消耗在JIT编译的时间

-XX:ErrorFile=./hs_err_pid<pid>.log 保存错误日志或者数据到文件中

-XX:-ExtendedDTraceProbes   开启solaris特有的dtrace探针

-XX:HeapDumpPath=./java_pid<pid>.hprof  指定导出堆信息时的路径或文件

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

-XX:OnError="<cmd args>;<cmd args>" 出现致命ERROR之后运行自定义命令

-XX:OnOutOfMemoryError="<cmd args>;<cmd args>"  当首次遭遇OOM时执行自定义命令

-XX:-PrintClassHistogram    遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同

-XX:-PrintConcurrentLocks   遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同

-XX:-PrintCommandLineFlags  打印在命令行中出现过的标记

-XX:-PrintCompilation   当一个方法被编译时打印相关信息

-XX:-PrintGC    每次GC时打印相关信息

-XX:+PrintGC Details    每次GC时打印详细信息

-XX:-PrintGCTimeStamps  打印每次GC的时间戳

-XX:-TraceClassLoading  跟踪类的加载信息

-XX:-TraceClassLoadingPreorder  跟踪被引用到的所有类的加载信息

-XX:-TraceClassResolution   跟踪常量池

-XX:-TraceClassUnloading    跟踪类的卸载信息

-XX:-TraceLoaderConstraints 跟踪类加载器约束的相关信息

三  jvm的垃圾收集器参数设置

3.1 查看默认垃圾收集器

-XX:+PrintCommandLineFlags:查看命令行相关参数(包含使用的垃圾收集器)

使用命令行指令:jinfo –flag 相关垃圾回收器参数 进程ID

3.2 串行收集器

Serial收集器作为HotSpot中Client模式下的默认新生代垃圾收集器。Serial Old是运行在Client模式下默认的老年代的垃圾回收器。

-XX:+UseSerialGC 

指定年轻代和老年代都使用串行收集器。等价于 新生代用Serial GC,且老年代用Serial Old GC。可以获得最高的单线程收集效率。

3.3 并行收集器

-XX:+UseParNewGC

手动指定使用ParNew收集器执行内存回收任务。它表示年轻代使用并行收集器,不影响老年代。

-XX:ParallelGCThreads=N 

限制线程数量,默认开启和CPU数据相同的线程数。

3.4.Parallel收集器

-XX:+UseParallelGC  手动指定年轻代使用Parallel并行收集器执行内存回收任务。

-XX:+UseParallelOldGC  手动指定老年代都是使用并行回收收集器。分别适用于新生代和老年代。默认jdk8是开启的。

上面两个参数,默认开启一个,另一个也会被开启。(互相激活)

-XX:ParallelGCThreads 设置年轻代并行收集器的线程数。一般地,最好与CPU数量相等,以避免过多的线程数影响垃圾收集性能。

在默认情况下,当CPU 数量小于8个, ParallelGCThreads 的值等于CPU 数量。

当CPU数量大于8个,ParallelGCThreads 的值等于3+[5*CPU_Count]/8] 。

-XX:MaxGCPauseMillis 设置垃圾收集器最大停顿时间(即STW的时间)。单位是毫秒。

为了尽可能地把停顿时间控制在MaxGCPauseMills以内,收集器在工作时会调整Java堆大小或者其他一些参数。

对于用户来讲,停顿时间越短体验越好。但是在服务器端,我们注重高并发,整体的吞吐量。所以服务器端适合Parallel,进行控制。

该参数使用需谨慎。

-XX:GCTimeRatio 垃圾收集时间占总时间的比例(= 1 / (N + 1))。用于衡量吞吐量的大小。

取值范围(0,100)。默认值99,也就是垃圾回收时间不超过1%。

与前一个-XX:MaxGCPauseMillis参数有一定矛盾性。暂停时间越长,Radio参数就容易超过设定的比例。

-XX:+UseAdaptiveSizePolicy  设置Parallel Scavenge收集器具有自适应调节策略

在这种模式下,年轻代的大小、Eden和Survivor的比例、晋升老年代的对象年龄等参数会被自动调整,已达到在堆大小、吞吐量和停顿时间之间的平衡点。

在手动调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆、目标的吞吐量(GCTimeRatio)和停顿时间(MaxGCPauseMills),让虚拟机自己完成调优工作。

3.5.CMS收集器

-XX:+UseConcMarkSweepGC 手动指定使用CMS收集器执行内存回收任务。

开启该参数后会自动将-XX:+UseParNewGC打开。即:ParNew(Young区用)+CMS(Old区用)+Serial Old的组合。

-XX:CMSlnitiatingOccupanyFraction 设置堆内存使用率的阈值,一旦达到该阈值,便开始进行回收。

JDK5及以前版本的默认值为68,即当老年代的空间使用率达到68%时,会执行一次CMS回收。JDK6及以上版本默认值为92% 

如果内存增长缓慢,则可以设置一个稍大的值,大的阈值可以有效降低CMS的触发频率,减少老年代回收的次数可以较为明显地改善应用程序性能。反之,如果应用程序内存使用率增长很快,则应该降低这个阈值,以避免频繁触发老年代串行收集器。因此通过该选项便可以有效降低Full GC的执行次数。

-XX:+UseCMSCompactAtFullCollection 用于指定在执行完Full GC后对内存空间进行压缩整理,以此避免内存碎片的产生。不过由于内存压缩整理过程无法并发执行,所带来的问题就是停顿时间变得更长了。

-XX:CMSFullGCsBeforeCompaction 设置在执行多少次Full GC后对内存空间进行压缩整理。

-XX:ParallelCMSThreads 设置CMS的线程数量。

CMS默认启动的线程数是(ParallelGCThreads+3)/4,ParallelGCThreads 是年轻代并行收集器的线程数。当CPU资源比较紧张时,受到CMS收集器线程的影响,应用程序的性能在垃圾回收阶段可能会非常糟糕。

CMS收集器还有如下常用参数:

-XX:ConcGCThreads:设置并发垃圾收集的线程数,默认该值是基于ParallelGCThreads计算出来的;

-XX:+UseCMSInitiatingOccupancyOnly:是否动态可调,用这个参数可以使CMS一直按CMSInitiatingOccupancyFraction设定的值启动

-XX:+CMSScavengeBeforeRemark:强制hotspot虚拟机在cms remark阶段之前做一次minor gc,用于提高remark阶段的速度;

-XX:+CMSClassUnloadingEnable:如果有的话,启用回收Perm 区(JDK8之前)

-XX:+CMSParallelInitialEnabled:用于开启CMS initial-mark阶段采用多线程的方式进行标记,用于提高标记速度,在Java8开始已经默认开启;

-XX:+CMSParallelRemarkEnabled:用户开启CMS remark阶段采用多线程的方式进行重新标记,默认开启;

-XX:+ExplicitGCInvokesConcurrent 、-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses这两个参数用户指定hotspot虚拟在执行System.gc()时使用CMS周期;

-XX:+CMSPrecleaningEnabled:指定CMS是否需要进行Pre cleaning这个阶段

注意说明:

JDK9新特性:CMS被标记为Deprecate(JEP291)

如果对JDK 9及以上版本的HotSpot虚拟机使用参数-XX:+UseConcMarkSweepGC来开启CMS收集器的话,用户会收到一个警告信息,提示CMS未来将会被废弃。

JDK14新特性:删除CMS垃圾回收器(JEP363)

移除了CMS垃圾收集器,如果在JDK14中使用-XX:+UseConcMarkSweepGC的话,JVM不会报错,只是给出一个warning信息,但是不会exit。JVM会自动回退以默认GC方式启动JVM

3.6.G1收集器

-XX:+UseG1GC  

手动指定使用G1收集器执行内存回收任务。

-XX:G1HeapRegionSize  

设置每个Region的大小。值是2的幂,范围是1MB到32MB之间,目标是根据最小的Java堆大小划分出约2048个区域。默认是堆内存的1/2000。

-XX:MaxGCPauseMillis   

设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到)。默认值是200ms

-XX:ParallelGCThread   

设置STW时GC线程数的值。最多设置为8

-XX:ConcGCThreads   

设置并发标记的线程数。将n设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右。

-XX:InitiatingHeapOccupancyPercent  

设置触发并发GC周期的Java堆占用率阈值。超过此值,就触发GC。默认值是45。

-XX:G1NewSizePercent、-XX:G1MaxNewSizePercent  

新生代占用整个堆内存的最小百分比(默认5%)、最大百分比(默认60%)

-XX:G1ReservePercent=10 

保留内存区域,防止to space(Survivor中的to区)溢出

注意:G1收集器主要涉及到Mixed GC,Mixed GC会回收young 区和部分old区。

G1关于Mixed GC调优常用参数:

-XX:InitiatingHeapOccupancyPercent:设置堆占用率的百分比(0到100)达到这个数值的时候触发global concurrent marking(全局并发标记),默认为45%。值为0表示间断进行全局并发标记。

-XX:G1MixedGCLiveThresholdPercent:设置Old区的region被回收时候的对象占比,默认占用率为85%。只有Old区的region中存活的对象占用达到了这个百分比,才会在Mixed GC中被回收。

-XX:G1HeapWastePercent:在global concurrent marking(全局并发标记)结束之后,可以知道所有的区有多少空间要被回收,在每次young GC之后和再次发生Mixed GC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生Mixed GC。

-XX:G1MixedGCCountTarget:一次global concurrent marking(全局并发标记)之后,最多执行Mixed GC的次数,默认是8。

-XX:G1OldCSetRegionThresholdPercent:设置Mixed GC收集周期中要收集的Old region数的上限。默认值是Java堆的10%

四  案例操作

4.1 案例

通过这些api可以监控我们的应用服务器的堆内存使用情况,设置一些阈值进行报警等处理。

/**
 *
 * 监控我们的应用服务器的堆内存使用情况,设置一些阈值进行报警等处理
 *
 * @author shkstart
 * @create 15:23
 */
public class MemoryMonitor {
    public static void main(String[] args) {
        MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
        MemoryUsage usage = memorymbean.getHeapMemoryUsage();
        System.out.println("INIT HEAP: " + usage.getInit() / 1024 / 1024 + "m");
        System.out.println("MAX HEAP: " + usage.getMax() / 1024 / 1024 + "m");
        System.out.println("USE HEAP: " + usage.getUsed() / 1024 / 1024 + "m");
        System.out.println("\nFull Information:");
        System.out.println("Heap Memory Usage: " + memorymbean.getHeapMemoryUsage());
        System.out.println("Non-Heap Memory Usage: " + memorymbean.getNonHeapMemoryUsage());

        System.out.println("=======================通过java来获取相关系统状态============================ ");
        System.out.println("当前堆内存大小totalMemory " + (int) Runtime.getRuntime().totalMemory() / 1024 / 1024 + "m");// 当前堆内存大小
        System.out.println("空闲堆内存大小freeMemory " + (int) Runtime.getRuntime().freeMemory() / 1024 / 1024 + "m");// 空闲堆内存大小
        System.out.println("最大可用总堆内存maxMemory " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "m");// 最大可用总堆内存大小

    }
}

获取系统内存:

public class HeapSpaceInitial {

    public static void main(String[] args) {

        //返回Java虚拟机中的堆内存总量

        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;

        //返回Java虚拟机试图使用的最大堆内存量

        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;

        System.out.println("-Xms : " + initialMemory + "M");

        System.out.println("-Xmx : " + maxMemory + "M");

        System.out.println("系统内存大小为:" + maxMemory * 4.0 / 1024 + "G");

        System.out.println("系统内存大小为:" + initialMemory * 64.0 / 1024 + "G");

    }

}

五 收集器的选择原则

5.1 垃圾收集器选取原则

优先调整堆的大小让JVM自适应完成。

如果内存小于100M,使用串行收集器

如果是单核、单机程序,并且没有停顿时间的要求,串行收集器

如果是多CPU、需要高吞吐量、允许停顿时间超过1秒,选择并行或者JVM自己选择

如果是多CPU、追求低停顿时间,需快速响应(比如延迟不能超过1秒,如互联网应用),使用并发收集器。官方推荐G1,性能高。现在互联网的项目,基本都是使用G1。

特别说明:

1. 没有最好的收集器,更没有万能的收集;

2. 调优永远是针对特定场景、特定需求,不存在一劳永逸的收集器

六  日均百万客流量的网站调优

6.1 案例

一天百万级订单这个绝对是现在顶尖电商公司交易量级,百万订单一般在4个小时左右产生,我们计算一下每秒产生多少订单,3000000/3600/4 = 208.3单/s,我们大概按照每秒300单来计算。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值