IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JVM系列之性能调优参考手册(实践篇) -> 正文阅读

[Java知识库]JVM系列之性能调优参考手册(实践篇)

JVM系列之性能调优参考手册(实践篇)

系列博客专栏:

1、前言介绍

前面章节的学习,我们对JVM的体系架构等等有了比较详细的了解,所以可以对这些理论进行实践,当然只是通过一些example,实践的生产环境要复杂得多,所以本博客只能作为学习参考资料。一般来说,JVM内部是经过很多的实践和优化的,所以一般调休是先通过java提供的工具进行性能问题排查,找出影响性能的代码,然后迫不得已才可以考虑调整JVM参数,进行JVM参数调优。

2、标准参数

标准参数以-开头,所有jvm都实现了该参数的功能

  • -help
    查看java命令帮助信息

  • -server -client
    两个参数用于设置虚拟机使用何种运行模式,client模式启动比较快,但运行时性能和内存管理效率不如server模式。相反,server模式启动比client慢,但是运行时性能和内存管理效率比较高。64bit版本默认设置-server

  • -version
    查看java版本,
    -cp -classpath
    指定classpath路径

  • -jar
    指定运行一个jar包,jar包中manifest文件中必须指定Main-class

  • -verbose
    打印jvm载入类的相关信息

  • -verbose:gc
    打印gc信息

  • -verbose:jni
    打印native方法调用信息

  • 等等,…

3、非标准参数

非标准参数以-X开头,给jvm实现这些参数的功能,但是不是所有的jvm都有这些功能。同时在不同JDK版本也有可能变动,所以说这些参数是非标准参数

  • -Xint
    解释执行
  • -Xcomp
    编译执行,第1次使用就编译成本地代码
  • -Xmixed
    混合模式,jvm自己决定
[www@localhost ~]$ java -Xint -version
java version "11.0.9" 2020-10-20 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.9+7-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.9+7-LTS, interpreted mode)

[www@localhost ~]$ java -Xcomp -version
java version "11.0.9" 2020-10-20 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.9+7-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.9+7-LTS, compiled mode)

[www@localhost ~]$ java -Xmixed -version
java version "11.0.9" 2020-10-20 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.9+7-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.9+7-LTS, mixed mode)
[www@localhost ~]$
  • -Xms
    eg:-Xms1g指定jvm初始内存为1g

  • -Xmx
    eg:-Xmx1g指定jvm最大可用内存为1g

  • -Xmn
    eg:-Xmn1g指定年轻代大小为1g,增加年轻代容量会缩小年老代容量

  • -Xss
    -Xss1m,设置线程堆栈大小,默认1m

  • -Xloggc
    eg:-Xloggc:gc.log,将gc日志记录到gc.log文件中

  • -Xprof
    跟踪正运行的程序,并将跟踪数据在标准输出输出

  • 等等,…

4、不稳定参数

no Stable,不稳定参数以 -XX开头,使用最多的参数类型,非标准化参数,相对不稳定,主要用于JVM调优和Debug

  • Boolean类型
    格式:-XX[+/-]<name>+ 表示启用,-表示禁用
    例子:-XX:+UseConcMarkSweepGC,表示启用CMS类型的垃圾回收器
  • 非Boolean类型
    格式:-XX<name>=<value>表示name属性的值是value
    例子:-XX:MaxGCPauseMillis=500
  • -XX:PermSize
    非堆,也可以说是方法区,内存初始大小
  • -XX:MaxPermSize
    方法区,最大内存大小
  • -XX:-UseSerialGC
    使用串行GC
  • -XX:-UseParallelGC
    使用并行GC
  • -XX:-UseConcMarkSweepGC
    对老年代使用CMS(Concurrent Mark And Sweep)GC
参数含义说明
-XX:CICompilerCount最大并行编译数如果设置大于1,会提高编译速度,但是同样影响系统稳定性,会增加jvm奔溃的可能
-XX:InitialHeapSize=100M初始化堆大小简写-Xms100M
-XX:MaxHeapSize=100M最大堆大小简写-Xms100M
-XX:NewSize=20M设置年轻代的大小
-XX:OldSize=50M设置老年代的大小
-XX:MetaspaceSize=50M设置方法区的大小
-XX:MaxMetaspaceSize=50M方法区最大大小
-XX:+UseParallelGC使用UseParallelGC并行收集器,作用于新生代,吞吐量优先
-XX:+UseParallelOldGC使用UseParallelOldGC并行收集器,作用于老年代,吞吐量优先
-XX:+UseConcMarkSweepGC使用CMS作用于老年代,停顿时间优先
-XX:+UseG1GC使用G1GC作用于新生代,老年代,停顿时间优先
-XX:NewRatio新老生代的比值比如-XX:Ratio=4,表示新生代:老年代=1:4,也就是新生代占整个堆内存的1/5
-XX:SurvivorRatio两个S区和Eden区的比值比如-XX:SurvivorRatio=8,也就是(S0+S1):Eden=2:8,也就是一个S占整个新生代的1/10
-XX:+HeapDumpOnOutOfMemoryError启动堆内存溢出打印当JVM堆内存发生溢出时,也就是OOM,自动生成dump文件
-XX:HeapDumpPath=heap.hprof指定堆内存溢出打印目录表示在当前目录生成一个heap.hprof文件
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:gc.log打印GC日志,保存到gc.log
-Xss128k设置每个线程的堆栈大小经验值是3000-5000最佳
-XX:MaxTenuringThreshold=15提升年老代的最大临界值默认值为 15
-XX:InitiatingHeapOccupancyPercent启动并发GC周期时堆内存使用占比默认值为 45.
-XX:G1HeapWastePercent允许的浪费堆空间的占比默认是10%,如果并发标记可回收的空间小于10%,则不会触发MixedGC
-XX:MaxGCPauseMillis=200MG1最大停顿时间暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的速度。从而造成full gc。
-XX:ConcGCThreads=n并发垃圾收集器使用的线程数量默认值随JVM运行的平台不同而不同
-XX:G1MixedGCLiveThresholdPercent=65混合垃圾回收周期中要包括的旧区域设置占用率阈值默占用率为 65%
-XX:G1MixedGCCountTarget=8设置标记周期完成后,对存活数据上限为G1MixedGCLIveThresholdPercent的旧区域执行混合垃圾回收的目标次数默认8次混合垃圾回收,混合回收的目标是要控制在此目标次数以内
-XX:G1OldCSetRegionThresholdPercent=1描述Mixed GC时,Old Region被加入到CSet中默认占用率为 65%
-XX:LargePageSizeInBytes=4m设置用于Java堆的大页面尺寸
-XX:MaxHeapFreeRatio=70GC后java堆中空闲量占的最大比例
-XX:MaxNewSize=size新生成对象能占用内存的最大值
-XX:MaxPermSize=64m老生代对象能占用内存的最大值
-XX:MinHeapFreeRatio=40GC后java堆中空闲量占的最小比例
-XX:ReservedCodeCacheSize=32m保留代码占用的内存容量
-XX:ThreadStackSize=512设置线程栈大小,若为0则使用系统默认值
-XX:+UseLargePages使用大页面内存
-XX:-CITime打印消耗在JIT编译的时间
-XX:ErrorFile=./hs_err_pid.log保存错误日志或者数据到文件中
-XX:-ExtendedDTraceProbes开启solaris特有的dtrace探针
-XX:OnError=”;“出现致命ERROR之后运行自定义命令
-XX:OnOutOfMemoryError=”;“当首次遭遇OOM时执行自定义命令
-XX:-PrintClassHistogram遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同
-XX:-PrintConcurrentLocks遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同
-XX:-PrintCommandLineFlags打印在命令行中出现过的标记
-XX:-PrintCompilation当一个方法被编译时打印相关信息
-XX:-TraceClassLoading跟踪类的加载信息
-XX:-TraceClassLoadingPreorder跟踪被引用到的所有类的加载信息
-XX:-TraceClassResolution跟踪常量池
-XX:-TraceClassUnloading跟踪类的卸载信息
-XX:-TraceLoaderConstraints跟踪类加载器约束的相关信息
[www@localhost ~]$ java -XX:+PrintFlagsFinal -version > log.txt
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

5、常用命令

  • jps

jps命令用于查看java进程

The jps command lists the instrumented Java HotSpot VMs on the target system. The
command is limited to reporting information on JVMs for which it has the access
permissions.

[www@localhost ~]$ jps
4352
8480 Jps
1736 RemoteMavenServer
3144 SmartGit
7612 Bootstrap
[www@localhost ~]$ jps -l
3024 sun.tools.jps.Jps
4352
1736 org.jetbrains.idea.maven.server.RemoteMavenServer
3144 SmartGit
7612 org.apache.catalina.startup.Bootstrap
  • jinfo
    jinfo命令用于实时查看和调整jvm配置参数

语法:

  • jinfo -flag name PID // 查看某个java进程的name属性的值
  • jinfo -flag [+/-] <name> PID // 启用禁用JVM属性
  • jinfo -flag <name>=<value> PID // 设置JVM参数(name)的值(value)

查看进程4352的MaxHeapSize属性

[www@localhost ~]$ jinfo -flag MaxHeapSize 4352
-XX:MaxHeapSize=786432000

jinfo修改MaxHeapSize值

 jinfo -flag MaxHeapSize=786432000 4352

jinfo -flag PID查看曾经赋过值的一些参数


[www@localhost ~]$ jinfo -flag 7612
Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    -flag <name>         to print the value of the named VM flag
    -flag [+|-]<name>    to enable or disable the named VM flag
    -flag <name>=<value> to set the named VM flag to the given value
    -flags               to print VM flags
    -sysprops            to print Java system properties
    <no option>          to print both of the above
    -h | -help           to print this help message
  • jstat
    查看虚拟机性能统计信息

The jstat command displays performance statistics for an instrumented Java
HotSpot VM. The target JVM is identified by its virtual machine identifier, or
vmid option.

查看类装载信息,例子,查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10次

[www@localhost ~]$ jstat -class 3760 1000 10
Loaded  Bytes  Unloaded  Bytes     Time
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27
 13080 26809.1      250   390.1      29.27

查看垃圾收集信息

[www@localhost ~]$ jstat -gc 3760 1000 10
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU
   CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 492086.2  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 502965.7  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 502965.7  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775
24576.0 48640.0 767.1   0.0   528896.0 502965.7  214528.0   109639.1  89856.0 87
215.8 9472.0 8955.5     28    0.965   4      0.810    1.775

  • jstack
    查看线程堆栈信息

The jstack command prints Java stack traces of Java threads for a specified Java
process, core file, or remote debug server.

语法:jstack PID

两个锁互相持有,造成死锁案例:


public class LockDemo
{
    public static void main(String[] args)
    {
        LockThread d1=new LockThread(true);
        LockThread d2=new LockThread(false);
        Thread t1=new Thread(d1);
        Thread t2=new Thread(d2);
        t1.start();
        t2.start();
    }
}
//定义锁对象
class MyLock{
    public static Object obj1=new Object();
    public static Object obj2=new Object();
}
// 案例,thread1持有u1的锁,thread2持有u2的锁,thread1等待获取u2的锁,thread2等待获取u1的锁
class LockThread implements Runnable{
    private boolean flag;
    LockThread(boolean flag){
    this.flag=flag;
    }
    public void run() {
        if(flag) {
            while(true) {
                synchronized(MyLock.obj1) {
                    System.out.println(Thread.currentThread().getName()+"获得obj1锁");
                            synchronized(MyLock.obj2) {
                                System.out.println(Thread.currentThread().getName()+"获得obj2锁");
                            }
                }
            }
        } else {
            while(true){
                synchronized(MyLock.obj2) {
                    System.out.println(Thread.currentThread().getName()+"获得obj2锁");
                        synchronized(MyLock.obj1) {
                            System.out.println(Thread.currentThread().getName()+"获得obj1锁");
                        }
                }
            }
        }
    }

}

jstack进行分析,

[www@localhost ~]$ jps -l
2560
2624 SmartGit
3760 org.apache.catalina.startup.Bootstrap
5316 org.jetbrains.idea.maven.server.RemoteMavenServer
7400 sun.tools.jps.Jps
8104 LockDemo
1116 org.jetbrains.jps.cmdline.Launcher

[www@localhost ~]$ jstack 8104

在这里插入图片描述

  • jmap
    生成堆转储快照

The jmap command prints shared object memory maps or heap memory details of a
specified process, core file, or remote debug server.

语法:

jmap -heap PID

在这里插入图片描述
dump出堆内存相关信息

jmap -dump:format=b,file=heap.hprof PID

在这里插入图片描述
当然可以设置发生堆内存溢出的时候,能自动dump出该文件,加上启动参数:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof

写个Threadlocal例子:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = {"/api"})
public class ThreadLocalHeapController {
	// ThreadLocal 内存溢出例子
    @GetMapping(value = "/testHeap")
    public ResponseEntity<?> testHeap() {
        ThreadLocal<Byte[]> threadLocal = new ThreadLocal<Byte[]>();
        try {
            threadLocal.set(new Byte[1024 * 1024]);
            return ResponseEntity.ok("success");
        }catch (Exception e) {
            return ResponseEntity.badRequest().build();
        } finally {
            // 不进行ThreadLocal remove会出现内存溢出
            //threadLocal.remove();
        }
    }

}

设置发生堆内存溢出的时候,能自动dump出日志文件

java -jar -Xms1000M -Xmx1000M -XX:+HeapDumpOnOutOfMemoryError -
XX:HeapDumpPath=jvm.hprof jvm-exception-example-0.0.1-SNAPSHOT.jar

在linux系统进行AB压测:10000次请求,并发100


[www@localhost ~]$ ab -n 10000 -c 100 http://127.0.0.1:8080/api/testHeap
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /api/testHeap
Document Length:        7 bytes

Concurrency Level:      100
Time taken for tests:   10.504 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1390000 bytes
HTML transferred:       70000 bytes
Requests per second:    952.01 [#/sec] (mean)
Time per request:       105.041 [ms] (mean)
Time per request:       1.050 [ms] (mean, across all concurrent requests)
Transfer rate:          129.23 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.7      0      10
Processing:     7  104  43.1    100    1223
Waiting:        7  100  38.8     99    1213
Total:          7  104  43.1    101    1224
WARNING: The median and mean for the initial connection time are not within a normal deviation
        These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
  50%    101
  66%    105
  75%    108
  80%    110
  90%    119
  95%    144
  98%    185
  99%    219
 100%   1224 (longest request)

jmap -heap PID再打印一下堆信息,可以看到并发的情况,内存溢出
在这里插入图片描述

当然拿到堆异常日志后,可以使用GCViewer等等根据进行性能分析,本博客只是以一个简单的例子进行分析,生产环境特别复杂,需要多年的经验和很好的耐心

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-09 17:29:59  更:2021-07-09 17:30:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/18 18:05:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码