JVM优化之优化常用参数和工具


内容提要

  • jvm运行参数和参数设置
  • jvm 内存模型
  • 定位分析死锁和内存溢出
  • 其他工具使用

为什么要优化JVM
1.生产环境需要承载更多的并发要求,对底层的优化能显著提升性能,节约成本
2.测试和生产环境的不同可能导致我们无法实时了解具体性能问题,我们需要借助对JVM了解分析问题所在。

jvm运行参数和参数设置

1.标准参数

由java -help检索出来的所有参数成为标准参数,未来发行版本中不会轻易修改,即使修改也会有官方通知

     >java -help-java [-options] class [args...] (执行类)或 java [-options] -jar jarfile [args...] #(执行 jar 文件)其中选项包括:-D<名称>=<值> #设置系统属性-version #输出产品版本并退出-showversion # 输出产品版本并继续-? -help 输出此帮助消息-X  #输出非标准选项的帮助-d32 #使用 32 位数据模型 (如果可用)-d64 #使用 64 位数据模型 (如果可用)-server #选择 "server" VM 默认 VM 是 server,因为您是在服务器类计算机上运行。-cp <目录和 zip/jar 文件的类搜索路径>-classpath <目录和 zip/jar 文件的类搜索路径> #用 : 分隔的目录, JAR 档案和 ZIP 档案列表, 用于搜索类文件。###########################以上为非常重要的参数 希望开发者一定要记住###########################-verbose:[class|gc|jni] #启用详细输出-version:<值> #警告: 此功能已过时, 将在未来发行版中删除。需要指定的版本才能运行-jre-restrict-search | -no-jre-restrict-search #警告: 此功能已过时, 将在未来发行版中删除。在版本搜索中包括/排除用户专用 JRE-ea[:<packagename>...|:<classname>]-enableassertions[:<packagename>...|:<classname>]#按指定的粒度启用断言-da[:<packagename>...|:<classname>]-disableassertions[:<packagename>...|:<classname>] #禁用具有指定粒度的断言-esa | -enablesystemassertions # 启用系统断言-dsa | -disablesystemassertions # 禁用系统断言-agentlib:<libname>[=<选项>] #加载本机代理库 <libname>, 例如 -agentlib:hprof另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help-agentpath:<pathname>[=<选项>] #按完整路径名加载本机代理库-javaagent:<jarpath>[=<选项>] #加载 Java 编程语言代理, 请参阅 java.lang.instrument-splash:<imagepath> # 使用指定的图像显示启动屏幕

使用Java代码测试系统属性

 Properties properties = System.getProperties();for (Map.Entry<Object, Object> objectObjectEntry : properties.entrySet()) {System.out.printf("system prop : %s = %s\n",objectObjectEntry.getKey(),objectObjectEntry.getValue());}
// java -Dmyname=huyiyu [类名] 之后在打印所有系统参数中找到myname=huyiyu

server和client参数

server: 显式指定-server时设置,或者64位系统时设置,使用 parNew GC 1 启动慢运行快
client:显式指定-client时设置,或者64位系统时设置,使用default GC2启动快运行慢
系统信息如下:

windowsX86 其他X86 其他X86 Mem:>2GB >2CPU X64
client client server server

2.非标准参数

-Xmixed # 混合模式执行 (默认)
-Xint #仅解释模式执行
-Xbatch #禁用后台编译
-Xms<size> #设置初始 Java 堆大小
-Xmx<size> #设置最大 Java 堆大小
-Xss<size> #设置 Java 线程堆栈大小
-XshowSettings #显示所有设置并继续
########################以上参数非常重要需要记住###############################
-XshowSettings:all#显示所有设置并继续
-XshowSettings:vm 显示所有与 vm 相关的设置并继续
-XshowSettings:properties #显示所有属性设置并继续
-XshowSettings:locale#显示所有与区域设置相关的设置并继续
-Xbootclasspath: <用 : 分隔的目录和 zip/jar 文件> #设置搜索路径以引导类和资源
-Xbootclasspath/a:<用 : 分隔的目录和 zip/jar 文件>#附加在引导类路径末尾
-Xbootclasspath/p:<用 : 分隔的目录和 zip/jar 文件>#置于引导类路径之前
-Xdiag #显示附加诊断消息
-Xnoclassgc #禁用类垃圾收集
-Xincgc #启用增量垃圾收集
-Xloggc:<file> #将 GC 状态记录在文件中 (带时间戳)
-Xprof #输出 cpu 配置文件数据
-Xfuture #启用最严格的检查, 预期将来的默认值
-Xrs #减少 Java/VM 对操作系统信号的使用 (请参阅文档)
-Xcheck:jni #对 JNI 函数执行其他检查
-Xshare:off #不尝试使用共享类数据
-Xshare:auto #在可能的情况下使用共享类数据 (默认)
-Xshare:on #要求使用共享类数据, 否则将失败。
#-X 选项是非标准选项, 如有更改, 恕不另行通知。

设置编译模式

类型 说明 示例 用法 备注
int 解释模式 -Xint -Xint 强制运行字节码,效率低
comp 编译模式 -Xcomp -Xcomp 编译成native代码带来大程度的优化
mix 混合模式 -Xmix -Xmix 解释和编译混合进行,由jvm决定使用任意推荐使用

设置初始堆内存

类型 说明 示例 用法 备注
Xms 最小堆内存 -Xms<数字><单位> -Xmx1024m 设置最小堆内存为1024MB
Xmx 最大堆内存 -Xmx<数字><单位> -Xms1024m 设置最大堆内存为1024MB
Xss 初始堆内存 -Xmx<数字><单位> -Xss1024m 设置初始堆内存为1024MB

XX参数

XX参数也是非标准参数,用于jvm调优和debug操作,设置JVM有两种模式分别如下

类型 用法 示例 备注
boolean -XX:+/-<name> XX:+DisableExplicitGC +:启用 -:禁用
非boolean :-XX:<name>=<value> :-XX:NewRatio=1
# XX参数实战
-XX:+PrintFlagsFinal -version# =表示默认参数 :=表示重置生效参数bool UseXMMForArrayCopy                       = true                                      {product} {default}bool UseXMMForObjInit                         = false                                {ARCH product} {default}bool UseXmmI2D                                = false                                {ARCH product} {default}bool UseXmmI2F                                = false                                {ARCH product} {default}bool UseXmmLoadAndClearUpper                  = true                                 {ARCH product} {default}bool UseXmmRegToRegMoveAll                    = true                                 {ARCH product} {default}bool VMThreadHintNoPreempt                    = false                                     {product} {default}intx VMThreadPriority                         = -1                                        {product} {default}intx VMThreadStackSize                        = 0                                      {pd product} {default}intx ValueMapInitialSize                      = 11                                     {C1 product} {default}intx ValueMapMaxLoopSize                      = 8                                      {C1 product} {default}intx ValueSearchLimit                         = 1000                                   {C2 product} {default}bool VerifyMergedCPBytecodes                  = true                                      {product} {default}bool VerifySharedSpaces                       = false                                     {product} {default}...
# 使用jinfo可查看运行的应用的jvm参数 :jinfo pid

jvm 内存模型

JDK1.7 jvm内存模型

jdk7 jvm 堆模型

  • Young 年轻区

Young区被划分为三部分,Eden区和两个大小严格相同的Survivor区,其中,Survivor区间中,某一时刻只有
其中一个是被使用的,另外一个留做垃圾收集时复制对象用,在Eden区间变满的时候, GC就会将存活的对
象移到空闲的Survivor区间中,根据JVM的策略,在经过几次垃圾收集后,任然存活于Survivor的对象将被移
动到Tenured区间。

  • Tenured 年老区

Tenured区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young复制转移一定的次数以
后,对象就会被转移到Tenured区,一般如果系统中用了application级别的缓存,缓存中的对象往往会被转
移到这一区间。

  • Perm 永久区

Perm代主要保存class,method,filed对象,这部份的空间一般不会溢出,除非一次性加载了很多的类,不过在
涉及到热部署的应用服务器的时候,有时候会遇到java.lang.OutOfMemoryError : PermGen space 的错误,
造成这个错误的很大原因就有可能是每次都重新部署,但是重新部署后,类的class没有被卸载掉,这样就造
成了大量的class对象保存在了perm中,这种情况下,一般重新启动应用服务器可以解决问题。

  • Virtual区

最大内存和初始内存的差值,就是Virtual区。

JDK1.8内存模型

JDK1.8的堆内存模型

由上图可以看出,jdk1.8的内存模型是由2部分组成,年轻代 + 年老代。
年轻代:Eden + 2*Survivor
年老代:OldGen
在jdk1.8中变化最大的Perm区,用Metaspace(元数据空间)进行了替换。
需要特别说明的是:Metaspace所占用的内存空间不是在虚拟机内部,而是在本地内存空间中,这也是与1.7的永
久代最大的区别所在。

JDK1.8废弃永久区的原因

This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need
to configure the permanent generation (since JRockit does not have a permanent
generation) and are accustomed to not configuring the permanent generation.
移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。
现实使用中,由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError: PermGen。
基于此,将永久区废弃,而改用元空间,改为了使用本地内存空间。

定位分析死锁和内存溢出

定位死锁

//以下是一段死锁代码
package com.yiyu;public class DeadLock {private static final String LOCK_A = "LOCK_A";private static final String LOCK_B = "LOCK_B";public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> DeadLock.getLock("thread_1", LOCK_A, LOCK_B));Thread thread2 = new Thread(() -> DeadLock.getLock("thread_2", LOCK_B, LOCK_A));thread1.start();thread2.start();}public static void getLock(String user, String lock1, String lock2) {try {synchronized (lock1) {System.out.println(user + "获得了" + lock1 + "的锁");synchronized (lock2) {System.out.println(user + "获得了" + lock2 + "的锁");}}} catch (Exception e) {e.printStackTrace();}}
}
# 使用jps查看进程ID
[root@izwz92w1juq9pnt03ae87yz ~]# jps
10400 Bootstrap
12812 Jps
12733 DeadLock
[root@izwz92w1juq9pnt03ae87yz ~]# jstack 12733
...
Found one Java-level deadlock:
=============================
"Thread-0":waiting to lock monitor 0x00007fa788008900 (object 0x00000000e34c2258, a java.lang.String),which is held by "Thread-1"
"Thread-1":waiting to lock monitor 0x00007fa788006900 (object 0x00000000e34c2228, a java.lang.String),which is held by "Thread-0"Java stack information for the threads listed above:
===================================================
"Thread-0":at DeadLock.getLock(DeadLock.java:17)- waiting to lock <0x00000000e34c2258> (a java.lang.String)- locked <0x00000000e34c2228> (a java.lang.String)at DeadLock.lambda$main$0(DeadLock.java:6)at DeadLock$$Lambda$1/0x0000000100060840.run(Unknown Source)at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)
"Thread-1":at DeadLock.getLock(DeadLock.java:17)- waiting to lock <0x00000000e34c2228> (a java.lang.String)- locked <0x00000000e34c2258> (a java.lang.String)at DeadLock.lambda$main$1(DeadLock.java:7)at DeadLock$$Lambda$2/0x0000000100062840.run(Unknown Source)at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)
Found 1 deadlock."Thread-0" #10 prio=5 os_prio=0 cpu=22.94ms elapsed=369.77s tid=0x00007fa7a8156000 nid=0x31c9 waiting for monitor entry  [0x00007fa79081b000]java.lang.Thread.State: BLOCKED (on object monitor)at DeadLock.getLock(DeadLock.java:17) #死锁发生的代码的行- waiting to lock <0x00000000e34c2258> (a java.lang.String)- locked <0x00000000e34c2228> (a java.lang.String)at DeadLock.lambda$main$0(DeadLock.java:6)at DeadLock$$Lambda$1/0x0000000100060840.run(Unknown Source)at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)"Thread-1" #11 prio=5 os_prio=0 cpu=23.86ms elapsed=369.77s tid=0x00007fa7a8157800 nid=0x31ca waiting for monitor entry  [0x00007fa79071a000]java.lang.Thread.State: BLOCKED (on object monitor)at DeadLock.getLock(DeadLock.java:17)#死锁发生的代码的行- waiting to lock <0x00000000e34c2228> (a java.lang.String)- locked <0x00000000e34c2258> (a java.lang.String)at DeadLock.lambda$main$1(DeadLock.java:7)at DeadLock$$Lambda$2/0x0000000100062840.run(Unknown Source)

定位内存溢出

package com.yiyu;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
public class OutOffMemoryErrorTest {public static void main(String[] args) {Stream.iterate(UUID.randomUUID().toString(), a -> a + a).limit(1000).reduce(String::concat).ifPresent(System.out::println);}
}

java -Xmx6m -XX:+HeapDumpOnOutOfMemoryError OutOffMemoryErrorTest 程序运行后会出现内存溢出
具体如下:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2176.hprof …
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
Heap dump file created [6383576 bytes in 0.029 secs]
at java.base/java.lang.String.concat(String.java:1947)
at com.yiyu.OutOffMemoryErrorTest$$Lambda$18/0x00000001000a8840.apply(Unknown Source)
at java.base/java.util.stream.ReduceOps$2ReducingSink.accept(ReduceOps.java:123)
at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
at java.base/java.util.stream.Stream1.tryAdvance(Stream.java:1231)atjava.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)atjava.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)atjava.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)atjava.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)atjava.base/java.util.stream.ReduceOps1.tryAdvance(Stream.java:1231) at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127) at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ReduceOps1.tryAdvance(Stream.java:1231)atjava.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)atjava.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)atjava.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)atjava.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)atjava.base/java.util.stream.ReduceOpsReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:558)
at com.yiyu.OutOffMemoryErrorTest.main(OutOffMemoryErrorTest.java:14)
从项目中找到对应的文件,使用工具分析

jvm其他工具使用

请参考博客jvm分析工具概述,对每个命令的每个操作分析的非常全面,跳转方便以后阅读。

JMX配置

原理是启动Java程序时添加系统参数已达到暴露端口提供接入虚拟机的协议,网上的配置非常详细但是有些不足,使用JMX时会开放三个端口,如果仅仅开启com.sun.management.jmxremote.port会发现 Jconsole活visualVM仍然访问不了,此时 使用netstat -nltp 查询打开另外两个端口或多一行配置即可,具体原因是因为JMX支持本地连接建立的端口。如需知道更详细信息请参考博客:JMX实践-JMX连接端口

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
javax.management.remote.rmi.RMIConnectorServer=9999

  1. 并行垃圾收集器 部分stw ↩︎

  2. 串行垃圾收集器单线程 全部stw ↩︎

JVM优化之优化常用参数和工具相关推荐

  1. JVM常用参数与工具

    原文出处:http://www.cnblogs.com/zhguang/p/java-jvm-gc.html 目录 参数设置 收集器搭配 启动内存分配 监控工具和方法 调优方法 调优实例       ...

  2. Java虚拟机学习总结(4)—— JVM 性能调优常用参数详解

    前言 在JVM性能调优时有三个组件: 堆大小调整(内存最够大的话,尽量搞大点) 垃圾收集器调整 JIT 编译器(比较深,需要掌握源码才能更好的优化更加底层) 大多数调优选项都与调整堆大小和为您的情况选 ...

  3. jvm堆空间的常用参数设置

  4. mysql参数优化步骤_MySQL架构优化实战系列4:SQL优化步骤与常用管理命令2(转)

    MySQL架构优化实战系列4:SQL优化步骤与常用管理命令 原文:http://dbaplus.cn/news-11-649-1.html 一.SQL语句优化步骤 1.查看MySQL状态及配置 sho ...

  5. 高级SQL优化(三) 常用优化工具 ——《12年资深DBA教你Oracle开发与优化——性能优化部分》...

    目录: Oracle数据完整性和锁机制  索引及优化之表分析  表分析.约束及表间关系  Oracle体系结构1 Oracle体系结构2  海量数据库及分区1  海量数据库及分区2  海量数据库及分区 ...

  6. MySQL系列之优化——1.优化哲学、2. 优化工具的使用、3. 优化思路分解、4. MySQL参数优化测试、5.1 参数优化、6. 参数优化结果、7. 锁的监控及处理、8. 主从优化

    文章目录 1.优化哲学 1.1 为什么优化? 1.2 优化风险 1.3 谁参与优化 1.4 优化方向 1.5 优化的范围及思路 优化效果和成本的评估: 2. 优化工具的使用 2.1 系统层面的 2.1 ...

  7. 深入理解JVM(4)——如何优化Java GC「译」

    本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇<How to Tune Java Garbage C ...

  8. JVM学习笔记之-堆,年轻代与老年代,对象分配过程,Minor GC、Major GC、Full GC,堆内存大小与OOM,堆空间分代,内存分配策略,对象分配内存,小结堆空间,逃逸分析,常用调优工具

    堆的核心概述 概述 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域.Java堆区在JVM 启动的时候即被创建,其空间大小也就确定了.是JVM管理的最大一块内存空间. 堆内存的大小是可 ...

  9. 一文了解程序员必须要知道的JVM和性能优化知识点

    目录 JVM和性能优化 1.Java内存区域 虚拟机的历史 未来的Java技术一览 运行时数据区域 站在线程角度来看堆和栈 深入辨析堆和栈 方法的出入栈 虚拟机中的对象 堆参数设置和内存溢出实战 2. ...

最新文章

  1. 多学一点(八)——LNMP环境搭建
  2. 链路负载均衡的链路和NAT地址保持
  3. 深度学习RNN实现股票预测实战(附数据、代码)
  4. 重学TCP协议(4) 三次握手
  5. nuxt 服务器构建因太耗CPU进程被杀解决办法
  6. tensorflow windows
  7. java程序嵌入地图_java – 使用JPA存储地图
  8. 揭密 GaussDB T 主备物理复制搭建过程(全)
  9. [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBuild+GitHub)
  10. python使用工具简介介绍
  11. 最大似然估计、MAP、贝叶斯估计
  12. java多线程总结一:线程的两种创建方式及比较
  13. 如何在虚拟机里用win95\98上网
  14. oracle导出dmp文件报错904,EXP-00008: 遇到 ORACLE 错误 904 ORA-01003
  15. Informatica使用工作流程及案例1
  16. 内存cpu占用不高但mysql很卡_为什么cpu占用率不高,内存也不高,电脑会卡
  17. 无奈.是爱是狠.金山毒霸2007.从此改邪归正
  18. 02好好学习读书笔记-- 黄金思考圈
  19. 【数学分析】从多元函数的定义一直到多元函数的泰勒展开
  20. hapi入门简介(入门实践)----净土小沙弥学hapi.js_第二篇

热门文章

  1. dnn降噪_万魔降噪双旗舰耳机分享:这两款无线耳机能否取代AirPods Pro?
  2. C语言 题目 1727: 首字母大写
  3. java web console,centos 8 如何开启 web console 界面?
  4. 字节跳动官方回应锤子科技员工改签,锤子二号员工入职OPPO...
  5. linux中的如何进行磁盘分区
  6. 2021年塔式起重机司机考试报名及塔式起重机司机模拟考试题
  7. 修改mySql最大连接数
  8. HarmonyOS/OpenHarmony按键设备键值
  9. cocos creator 2.4.3cc.assetManager.loadRemote 加载不了微信头像
  10. Es6新特性:set