基于jdk1.8的Java服务监控和性能调优

news/2024/12/28 14:31:37/

JVM的参数类型

X参数

  • 非标准参数
  • -Xint: 解释执行
  • -Xcomp: 第一次使用就编译成本地代码
  • -Xmixed: JVM自己来决定是否编译成本地代码

默认使用的是mixed mode

用的不多, 只需要做了解, 用的比较多的是XX参数

XX参数

  • 非标准化参数
  • 相对不稳定
  • 主要用来JVM调优和Debug

Boolean:

  • 格式: -XX:[+-]<name> 表示启用或禁用name属性
  • 比如: -XX:+UseConcMarkSweepGC , 表示启用了CMS垃圾收集器
  • -XX:+UseG1GC , 表示启用了G1垃圾收集器

非Boolean类型:

  • 格式: -XX:<name>=<value>表示name属性的值是value
  • 比如:-XX:MaxGCPauseMillis=500 , GC的最大停顿时间为500ms
  • -XX:GCTimeRatio=19, 表示垃圾回收时间最长不会超过总运行时间的 1/20

-Xmx -Xms

  • 不是X参数, 而是XX参数

-Xms等价于-XX:InitialHeapSize

-Xmx等价于-XX:MaxHeapSize

查看JVM运行时参数

常见参数

  • -XX:+PrintFlagsInitial , 查看程序运行的初始值
  • -XX:+PrintFlagsFinal , 查看最终的值, 因为初始值可能会被修改(命令或程序修改)
  • -XX:+UnlockExperimentalVMOptions , 解锁实验参数, 因为JVM中并不是所有的参数都可以直接赋值, 需要先使用这个参数才可以进行赋值
  • -XX:+UnlockDiagnosticVMOptions , 解锁诊断参数
  • -XX:+PrintcommandLineFlags , 打印命令行参数

使用示例: java -XX:+PrintFlagsFinal -version

这里查看的仅仅是调用java命令的当前进程的配置值, 后续会使用jinfo查看启动后的进程的参数配置

jps

可以根据网站查询具体的jps使用方法:

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html#CHDCGECD

包含JVM命令的所有使用方法: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html

jps

jps -l

jinfo

查看最大内存:

jinfo -flag MaxHeapSize <pid>

查看垃圾回收器:

jinfo -flag UseConcMarkSweepGC <pid>
jinfo -flag UseG1GC <pid>
jinfo -flag UseParallelGC <pid>

可以看出使用的是并行回收的垃圾回收器

jstat查看JVM统计信息

命令格式:

options :

  • -class: 查看类加载信息
  • -compiler: 查看编译信息
  • -gc: 查看GC信息
  • -printcompilation: 查看JIT编译信息

类装载

# 1000 输出间隔1000ms 10 表示输出总次数为10次
jstat -class <pid> 1000 10

垃圾收集

-gc , -gutil , -gccause , -gcnew , -gcold

所有的输出含义都可以在上文中提到的网站中进行查询

  • Young区:
    • S0C:当前 Survivor Space 0 的容量(kB)。
    • S1C:当前 Survivor Space 1 的容量(kB)。
    • S0U:Survivor Space 0 的利用率(kB)。
    • S1U:Survivor Space 1 的利用率(kB)。
    • EC:当前 Eden Space 的容量(kB)。
    • EU :Eden Space 的利用率(kB)。
  • Old区:
    • OC:当前 Old Space 的容量(kB)。
    • OU:Old Space 的利用率(kB)。
  • MC:Metaspace 的容量(kB)。
  • MU:Metaspace 的利用率(kB)。
  • CCSC:压缩类空间的容量(kB)。
  • CCSU:压缩类空间的使用情况(kB)。
  • YGC:Young Generation 垃圾回收事件的数量。
  • YGCT:Young Generation 垃圾回收时间。
  • FGC:Full GC 事件的数量。
  • FGCT:Full GC 时间。
  • GCT:垃圾回收总时间。

JVM内存结构:

JIT编译

-compiler , -printcompilation

  • Compiled:执行的编译任务数量。
  • Failed:编译任务失败的数量。
  • Invalid:被失效的编译任务数量。
  • Time:执行编译任务所花费的时间。
  • FailedType:最后一个失败编译任务的编译类型。
  • FailedMethod:最后一个失败编译任务的类名和方法名。

jmap+MAT实战内存溢出

如何导出内存映像文件

  • 内存溢出自动导出
    • -XX:+HeapDumpOnOutOfMemoryError, 启用内存溢出时自动导出
    • -XX:HeapDumpPath=./ , 指定导出文件的路径
  • 使用jmap命令手动导出
    • option: -heap, -clstats, -dump: <dump-options>, -F

  • <none>: 打印共享对象映射
  • -dump: 将Java堆内存以hprof二进制格式转储到文件中
  • -finalizerinfo: 打印等待终结的对象信息
  • -heap: 打印垃圾收集器使用情况、
  • -histo: 打印堆直方图,包括Java类的对象数量、内存大小和完全限定类名
  • -clstats: 打印每个类加载器的统计信息,包括名称、活动状态、地址、父类加载器以及已加载的类数和大小
  • -F: 强制模式,用于在pid不响应时使用-dump或-histo选项
  • -h或-help: 打印帮助信息
  • -J flag: 将flag传递给运行jmap命令的Java虚拟机
# dump出运行程序的堆状态, 以二进制文件格式保存到当前命令路径下的heap.hprof
jmap -dump:format=b,file=heap.hprof 48954

双击文件直接在IDEA中就可以直接查看分析结果:

分析内存溢出

测试触发内存溢出

测试com.imooc.monitor_tuning.chapter2.MemoryController#heap

idea程序启动运行参数:

-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./data

请求: http://localhost:8080/heap

使用mat分析内存对象

使用mat查看:提示可能内存溢出的是某个controller

查看GC Roots, 排除弱引用,软引用等,只看强引用

分析得知: Tomcat的thread引用了一个MemoryController, MemoryController引用了一个UserList, list里面是所有的User对象

使用mat查看对象占的字节数

使用IDEA自带的进行分析

jstack实战死循环与死锁

一般CPU飙升很有可能就是死循环之类, 这时候就需要定位哪个线程出了问题

基本使用

  • jstack [ options ] pid:打印指定进程 ID 的 Java 进程的堆栈跟踪信息。
  • jstack [ options ] executable core:打印从指定 Java 可执行文件生成的核心转储文件的堆栈跟踪信息。
  • jstack [ options ] [ server-id @ ] remote-hostname-or-IP:打印远程调试服务器主机名或 IP 地址上的 Java 进程的堆栈跟踪信息。
  • -F:当 jstack [ -l ] pid 没有响应时,强制进行堆栈转储。
  • -l:打印有关锁的其他信息,例如 java.util.concurrent 可拥有同步器的列表。有关 AbstractOwnableSynchronizer 类的说明,请参见 http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/AbstractOwnableSynchronizer.html 。
  • -m:打印混合模式堆栈跟踪,其中包含 Java 和本地 C/C++ 帧。

其中,pid 表示进程 ID,executable 表示 Java 可执行文件,core 表示核心转储文件,remote-hostname-or-IP 表示远程调试服务器主机名或 IP 地址,server-id 是可选的唯一 ID,用于在同一远程主机上运行多个调试服务器时进行区分。jps 命令可以用于获取在计算机上运行的 Java 进程列表,jsadebugd 命令可以用于启动远程调试服务器。

简单实用:

# 指定pid简单输出分析一下
jstack 61091 > data/61091.txt

线程生命周期和状态:

具体可以参考: JAVA线程状态及状态间转换介绍 | 盖娅计划

死循环分析

打包程序为jar包到远程服务器进行运行

上传服务器:

# 需要改为你自己的服务器用户和ip地址
scp target/monitor_tuning-0.0.1-SNAPSHOT.jar root@172.16.237.144:/root/

登录服务器,然后启动服务:

java -jar monitor_tuning-0.0.1-SNAPSHOT.jar

浏览器访问: http://172.16.237.144:8080/loop , 可以多开几个窗口访问

再开一个服务端的端口进行查看负载和进程:

打印stack信息:

jstack 36850 > 36850.txt

查看对应的进程的线程信息:

# 用于查看进程 36850 的线程信息。具体来说,-p 选项指定要查看的进程 ID,-H 选项表示显示线程层次结构。
top -p 36850 -H

由于Stack的信息是16进制,所以需要打印一下:

printf "%x" 36870

得到对应的16进制的线程id为9006, 然后打开前面的打印的栈信息进行查看,

这里可以下载下来用一些软件查看,不建议使用vim直接在线上环境打开 36850.txt,这里只是测试这样查看

vim 36850.txt
## /9006 即可找到

定位到是com.imooc.monitor_tuning.chapter2.CpuController.getPartneridsFromJson 这个方法导致CPU升高, 最后检查代码进行修复

死锁分析

浏览器访问: http://172.16.237.144:8080/deadlock

jps查看程序的java进程:

同样适用jstack打印栈信息:

jstack 37143 > 37143.txt
vim 37143.txt

翻到文件末尾, 可以发现死锁的两个线程信息和对应的方法名


http://www.ppmy.cn/news/69509.html

相关文章

嘉兴桐乡会计考证实操-考初级会计真的有用吗?

一边说着&#xff1a;考初级会计门槛太低了&#xff0c;谁都能考&#xff1b;一边又争先恐后的去报考&#xff0c;考初级会计真的是有用的吗&#xff1f;为什么这么多人一边说考了没用却一直在努力备考呢&#xff1f; 关于这类的话题&#xff0c;其实一直都存在&#xff0c;但不…

(数据结构)栈的实现——再一次保姆级教学

目录 1. 栈 ​编辑 1.2 栈的实现 2. 代码的实现 2.1 初始化栈和销毁栈 2.2栈顶元素的插入 2.3栈顶元素的删除 栈元素删除 2.4栈顶元素的获取和栈元素的个数 1. 栈 1.1 栈的概念和结构 栈(Stack)是一种线性存储结构&#xff0c;它具有如下特点&#xff1a; &#xff0…

【网络】Socket编程-TCP篇

文章目录 简单的TCP网络程序服务器:服务端创建套接字socket函数 服务端绑定bind函数bzero函数引入命令行参数 服务端监听listen函数 服务端获取连接accept函数 测试上述的功能telnet命令 服务端处理请求(提供服务)read函数write函数 tcp_server.cc客户端客户端创建套接字引入命…

【数据结构】栈的详解

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C语言和数据结构 &#x1f33c;博客专栏&#xff1a;数据结构 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&…

20 散列表的查找

散列表的查找 简介&#xff1a;散列表&#xff08;也成哈希表&#xff09;是一种高效的数据结构&#xff0c;他可以在平均复杂度为O(1)的情况下实现查找、插入和删除操作。 哈希表的基本思想是根据关键字的值来计算其应存储的位置。这个计算过程就是通过哈希函数来实现的。 根…

针对大集群node 对 Kubernetes 集群七大优化大法

一、节点配额和内核参数调整 对于公有云上的 Kubernetes 集群&#xff0c;规模大了之后很容器碰到配额问题&#xff0c;需要提前在云平台上增大配额。这些需要增大的配额包括&#xff1a; 虚拟机个数vCPU 个数内网 IP 地址个数公网 IP 地址个数安全组条数路由表条数持久化存储…

深度学习 -- 逻辑回归 PyTorch实现逻辑回归

前言 线性回归解决的是回归问题&#xff0c;而逻辑回归解决的是分类问题&#xff0c;这两种问题的区别是前者的目标属性是连续的数值类型&#xff0c;而后者的目标属性是离散的标称类型。 可以将逻辑回归视为神经网络的一个神经元&#xff0c;因此学习逻辑回归能帮助理解神经…

Java 中的访问修饰符有什么区别?

Java 中的访问修饰符用于控制类、类的成员变量和方法的访问权限&#xff0c;主要有以下四种&#xff1a; public&#xff1a;公共访问修饰符&#xff0c;可以被任何类访问。public 修饰的类、成员变量和方法可以在任何地方被访问到。 protected&#xff1a;受保护的访问修饰符…