JVM调优知识
1. 基本概念
1. 数据类型
1. 基本类型
byte,short,int,long,char,float,double,Boolean
2. 引用类型
类类型,接口类型,数组
2. 堆与栈
1. 栈是运行时的单位
2. 堆是存储的单位
2. 性能监控工具
1. jinfo
显示jvm的信息,启动参数等
jinfo pid
Attaching to process ID 28743, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.212-b10 Java System Properties: java.runtime.name = Java(TM) SE Runtime Environment java.vm.version = 25.212-b10 sun.boot.library.path = /usr/java/jdk1.8.0_212-amd64/jre/lib/amd64 java.protocol.handler.pkgs = org.springframework.boot.loader java.vendor.url = http://java.oracle.com/ java.vm.vendor = Oracle Corporation path.separator = : file.encoding.pkg = sun.io java.vm.name = Java HotSpot(TM) 64-Bit Server VM sun.os.patch.level = unknown sun.java.launcher = SUN_STANDARD user.country = CN user.dir = /home/java java.vm.specification.name = Java Virtual Machine Specification PID = 28743 java.runtime.version = 1.8.0_212-b10 java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment os.arch = amd64 java.endorsed.dirs = /usr/java/jdk1.8.0_212-amd64/jre/lib/endorsed line.separator = java.io.tmpdir = /tmp java.vm.specification.vendor = Oracle Corporation os.name = Linux sun.jnu.encoding = UTF-8 java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib spring.beaninfo.ignore = true sun.nio.ch.bugLevel = java.specification.name = Java Platform API Specification java.class.version = 52.0 java.net.preferIPv4Stack = true sun.management.compiler = HotSpot 64-Bit Tiered Compilers os.version = 2.6.32-431.el6.x86_64 user.home = /home/java user.timezone = GMT+8 catalina.useNaming = false java.awt.printerjob = sun.print.PSPrinterJob file.encoding = UTF-8 java.specification.version = 1.8 catalina.home = /tmp/tomcat.9114291105181748790.8082 user.name = java java.class.path = /usr/local/tomcat-vendor/zhen-vendor-2.0.0.jar java.vm.specification.version = 1.8 sun.arch.data.model = 64 sun.java.command = /usr/local/tomcat-vendor/zhen-vendor-2.0.0.jar java.home = /usr/java/jdk1.8.0_212-amd64/jre user.language = zh java.specification.vendor = Oracle Corporation awt.toolkit = sun.awt.X11.XToolkit java.vm.info = mixed mode java.version = 1.8.0_212 java.ext.dirs = /usr/java/jdk1.8.0_212-amd64/jre/lib/ext:/usr/java/packages/lib/ext sun.boot.class.path = /usr/java/jdk1.8.0_212-amd64/jre/lib/resources.jar:/usr/java/jdk1.8.0_212-amd64/jre/lib/rt.jar:/usr/java/jdk1.8.0_212-amd64/jre/lib/sunrsasign.jar:/usr/java/jdk1.8.0_212-amd64/jre/lib/jsse.jar:/usr/java/jdk1.8.0_212-amd64/jre/lib/jce.jar:/usr/java/jdk1.8.0_212-amd64/jre/lib/charsets.jar:/usr/java/jdk1.8.0_212-amd64/jre/lib/jfr.jar:/usr/java/jdk1.8.0_212-amd64/jre/classes java.awt.headless = true java.vendor = Oracle Corporation catalina.base = /tmp/tomcat.9114291105181748790.8082 file.separator = / java.vendor.url.bug = http://bugreport.sun.com/bugreport/ sun.io.unicode.encoding = UnicodeLittle sun.cpu.endian = little sun.cpu.isalist = VM Flags: Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=2147483648 -XX:MaxHeapSize=2147483648 -XX:MaxNewSize=715653120 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=715653120 -XX:OldSize=1431830528 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC Command line: -Xms2048m -Xmx2048m -Duser.timezone=GMT+8 -Djava.net.preferIPv4Stack=true
2. jps
查看java进程
3. jstat
查看jvm统计信息
1. 类加载的统计信息
jstat -class 28743 1000 10 每1000ms查看一次类加载情况,总共看10次
输出结果:
Loaded Bytes Unloaded Bytes Time
13287 25960.3 121 174.7 6.80
| 字段名 | 说明 |
|---|---|
| Loaded | 类加载器加载的类的数量 |
| Bytes | 类加载器加载的类的字节数 |
| Unloaded | 类加载器未加载的类的数量 |
| Bytes | 类加载器未加载的类的字节数 |
| Time | 执行类加载和卸载操作所花费的时间 |
2. 与编译器有关的统计信息
jstat -compiler 28743 1000 5
输出结果:
Compiled Failed Invalid Time FailedType FailedMethod
13715 3 0 46.83 1 com/mysql/jdbc/AbandonedConnectionCleanupThread run
| 字段名 | 说明 |
|---|---|
| Compiled | 执行的编译任务数 |
| Failed | 编译任务失败的次数 |
| Invalid | 无效的编译任务数 |
| Time | 执行编译任务所花费的时间 |
| FailedType | 上次编译失败的编译类型 |
| FailedMethod | 上次编译失败的类名和方法 |
3. 与垃圾回收有关的统计信息
1. jstat -gc 179767
堆内存 = 年轻代 + 年老代 + 永久代 + 元数据区
年轻代 = Eden区 + 两个Survivor区(From和To)
| 字段名 | 说明 |
|---|---|
| S0C | 第一个Survivor的容量(kB) |
| S1C | 第二个Survivor的容量(kB) |
| S0U | 第一个Survivor已使用的容量(kB) |
| S1U | 第二个Survivor已使用的容量(kB) |
| EC | Eden区的容量(kB) |
| EU | Eden区已使用的容量(kB) |
| OC | 老年代的容量(kB) |
| OU | 老年代已使用的容量(kB) |
| MC | 元空间的容量(kB) |
| MU | 元空间已使用的容量(kB) |
| CCSC | 压缩类的容量(kB) |
| CCSU | 压缩类已使用的的容量(kB) |
| YGC | 年轻代垃圾收集的次数 |
| YGCT | 年轻代垃圾回收消耗时间 |
| FGC | Full 垃圾回收次数 |
| FGCT | Full 垃圾回收消耗时间 |
| GCT | 垃圾回收消耗总时间 |
输出结果 
4. jstack
5. jmap
3. 垃圾回收器
1. 串行回收器
1. 特点
- 它仅仅使用单线程进行垃圾回收
- 它是独占式的垃圾回收
- 进行垃圾回收时, Java应用程序中的线程都需要暂停(Stop-The-World)
- 使用复制算法
- 适合CPU等硬件不是很好的场合
- 通常老年代垃圾回收比新生代回收要更长时间, 所以可能会使应用程序停顿较长时间
2. 参数
-XX:+UseSerialGC 新生代, 老年代都使用串行回收器
2. 并行回收器
1. 新生代ParNew回收器
特点
- 将串行回收多线程化
- 使用复制算法
- 垃圾回收时, 应用程序仍会暂停, 只不过由于是多线程回收, 在多核CPU上,回收效率会高于串行回收器, 反之在单核CPU, 效率会不如串行回收器
设置参数
|
1
2
3
|
-XX:+UseParNewGC 新生代使用ParNew回收器, 老年代使用串行回收器-XX:+UseConcMarkSweepGC 新生代使用ParNew回收器, 老年代使用CMS回收器-XX:ParallelGCThreads=n 指定ParNew回收器工作时的线程数量, cpu核数小时8时, 其值等于cpu数量, 高于8时,可以使用公式(3+((5*CPU_count)/8)) |
2. 新生代ParallelGC回收器
特点
- 同ParNew回收器一样, 不同的地方在于,它非常关注系统的吞吐量(通过参数控制)
- 使用复制算法
- 支持自适应的GC调节策略
设置参数
|
1
2
3
4
5
|
-XX:+UseParallelGC 新生代用ParallelGC回收器, 老年代使用串行回收器-XX:+UseParallelOldGC 新生代用ParallelGC回收器, 老年代使用ParallelOldGC回收器系统吞吐量的控制:-XX:MaxGCPauseMillis=n(单位ms) 设置垃圾回收的最大停顿时间,-XX:GCTimeRatio=n(n在0-100之间) 设置吞吐量的大小, 假设值为n, 那系统将花费不超过1/(n+1)的时间用于垃圾回收-XX:+UseAdaptiveSizePolicy 打开自适应GC策略, 在这种模式下, 新生代的大小, eden,survivior的比例, 晋升老年代的对象年龄等参数会被自动调整,以达到堆大小, 吞吐量, 停顿时间之间的平衡点 |
3. 老年代ParallelOldGC回收器
特点
- 同新生代的ParallelGC回收器一样, 是属于老年代的关注吞吐量的多线程并发回收器
- 使用标记压缩算法
设置参数
|
1
2
|
-XX:+UseParallelOldGC 新生代用ParallelGC回收器, 老年代使用ParallelOldGC回收器, 是非常关注系统吞吐量的回收器组合, 适合用于对吞吐量要求较高的系统-XX:ParallelGCThreads=n 指回ParNew回收器工作时的线程数量, cpu核数小时8时, 其值等于cpu数量, 高于8时, 可以使用公式(3+((5*CPU_count)/8)) |
3. CMS回收器
1. 老年代的并发回收器
特点
- 是并发回收, 非独占式的回收器, 大部分时候应用程序不会停止运行
- 针对年老代的回收器
- 使用并发标记清除算法, 因此回收后会有内存碎片, 可以使参数设置进行内存碎片的压缩整理
- 与ParallelGC和ParallelOldGC不同, CMS主要关注系统停顿时间
主要步骤
- 初始标记
- 并发标记
- 预清理
- 重新标记
- 并发清理
- 并发重置
需要注意:初始标记与重新标记是独占系统资源的,不能与用户线程一起执行,而其它阶段则可以与用户线程一起执行
设置参数
|
1
2
3
4
5
6
7
8
9
10
11
|
-XX:-CMSPrecleaningEnabled 关闭预清理, 不进行预清理, 默认在并发标记后, 会有一个预清理的操作,可减少停顿时间-XX:+UseConcMarkSweepGC 老年代使用CMS回收器, 新生代使用ParNew回收器-XX:ConcGCThreads=n 设置并发线程数量,-XX:ParallelCMSThreads=n 同上, 设置并发线程数量,-XX:CMSInitiatingOccupancyFraction=n 指定老年代回收阀值, 即当老年代内存使用率达到这个值时, 会执行一次CMS回收,默认值为68, 设置技巧: (Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100)>=Xmn-XX:+UseCMSCompactAtFullCollection 开启内存碎片的整理, 即当CMS垃圾回收完成后, 进行一次内存碎片整理, 要注意内存碎片的整理并不是并发进行的, 因此可能会引起程序停顿-XX:CMSFullGCsBeforeCompation=n 用于指定进行多少次CMS回收后, 再进行一次内存压缩-XX:+CMSParallelRemarkEnabled 在使用UseParNewGC 的情况下, 尽量减少 mark 的时间-XX:+UseCMSInitiatingOccupancyOnly 表示只有达到阀值时才进行CMS回收-XX:+CMSConcurrentMTEnabled 当该标志被启用时,并发的CMS阶段将以多线程执行,默认开启-XX:+CMSIncrementalMode 在增量模式下,CMS 收集器在并发阶段,不会独占整个周期,而会周期性的暂停,唤醒应用线程。收集器把并发阶段工作,划分为片段,安排在次级(minor) 回收之间运行。这对需要低延迟,运行在少量CPU服务器上的应用很有用。 |
4. G1回收器
1. 特点
- 独特的垃圾回收策略, 属于分代垃圾回收器
- 使用分区算法, 不要求eden, 年轻代或老年代的空间都连续
- 并行性:回收期间, 可由多个线程同时工作, 有效利用多核cpu资源
- 并发性:与应用程序可交替执行, 部分工作可以和应用程序同时执行
- 分代GC::分代收集器, 同时兼顾年轻代和老年代
- 空间整理:回收过程中, 会进行适当对象移动, 减少空间碎片
- 可预见性:G1可选取部分区域进行回收, 可以缩小回收范围, 减少全局停顿
2. 主要步骤
- 新生代GC
- 并发标记周期
- 混合回收
- 若需要,会进行FullGC
3. 设置参数
-XX:+UseG1GC 打开G1收集器开关,
-XX:MaxGCPauseMillis=n 指定目标的最大停顿时间,任何一次停顿时间超过这个值, G1就会尝试调整新生代和老年代的比例, 调整堆大小, 调整晋升年龄 -XX:ParallelGCThreads=n 用于设置并行回收时, GC的工作线程数量 -XX:InitiatingHeapOccpancyPercent=n 指定整个堆的使用率达到多少时, 执行一次并发标记周期, 默认45, 过大会导致并发标记周期迟迟不能启动, 增加FullGC的可能, 过小会导致GC频繁, 会导致应用程序性能有所下降4. 参数选项
| 选项 | 默认值 | 描述 |
| -XX:+UseG1GC | 默认关闭 | 使用G1垃圾处理器 |
| -XX:MaxGCPauseMillis=n | 默认值:4294967295 | 设置并行收集最大暂停时间,这是一个理想目标,JVM将尽最大努力来实现它。 |
| -XX:InitiatingHeapOccupancyPercent=n | 默认值:45 | 启动一个并发垃圾收集周期所需要达到的整堆占用比例。这个比例是指整个堆的占用比例而不是某一个代(例如G1),如果这个值是0则代表‘持续做GC’。默认值是45 |
| -XX:NewRatio=n | 默认值:2 | 设置年轻代和年老代的比值。例如:值为3,则表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4。 |
| -XX:SurvivorRatio=n | 默认值:8 | 年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 |
| -XX:MaxTenuringThreshold=n | 默认值:15 | 设置垃圾最大存活阀值。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。 |
| -XX:ParallelGCThreads=n | 默认值:随JVM运行平台不同而异 | 配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。 |
| -XX:ConcGCThreads=n | 默认值:随JVM运行平台不同而异 | 并行垃圾收集时,使用的线程数。默认值和JVM运行的平台有关。 |
| -XX:G1ReservePercent=n | 默认值:10 | 设置保留用来做假天花板以减少晋升(新生代对象晋升到老生代)失败可能性的堆数目。 |
| -XX:G1HeapRegionSize=n | 默认值根据堆大小而定 | 使用G1垃圾回收器,java堆被划分成统一大小的区块。这个选项设置每个区块的大小。最小值是1Mb,最大值是32Mb。 |

浙公网安备 33010602011771号