Java web应用性能分析之【java进程问题分析工具】
Java web应用性能分析之【java进程问题分析概叙】-CSDN博客
前面大概讲了java进程问题分析流程,这里再小结一下分析工具,后面也会小结一下java进程问题分析定位。
1.分析工具
1.1.linux命令工具
参考:Java web应用性能分析之【Linux服务器性能监控分析概叙】_web应用 cpu密集型-CSDN博客
1.2.jdk自带分析工具
在JDK的bin目录下有很多命令行工具,各个工具的大小基本上都稳定在27kb左右,这个不是JDK开发团队刻意为之的,而是因为这些工具大多数是jdk\lib\tools.jar类库的一层薄包装而已,他们的主要功能代码是在tools类库中实现的。命令行工具的好处是:当应用程序部署到生产环境后,无论是直接接触物理服务器还是远程telnet到服务器上都会受到限制。而借助tools.jar类库里面的接口,我们可以直接在应用程序中实现功能强大的监控分析功能。
常用命令:
1、jps:JVM Process Status Tool,现实指定系统内所有的HotSpot虚拟机进程 查看本机java进程信息;jinfo:Configuration Info for Java,虚拟机配置信息, 查看jvm和系统参数信息。
2、jstack:Stack Track for java ,显示虚拟机线程快照,打印线程的栈信息,制作 线程dump文件
3、jmap: Memory map for java,生成虚拟机的内存转储快照,打印内存映射信息,制作 堆dump文件
4、jstat:JVM Statistics Monitoring Tool,用于收集Hotspot虚拟机各个方面的运行参数 ,gc性能监控工具。
5、jhat:内存分析工具,JVM heap Dunp Browser,用于分析heapdump文件,他会建立一个HTTP/HTML服务,让用户可通过浏览器查看 。
jhat是sun提供的dump分析工具,上面讲过分析dump的工具还有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer等,一般这个命令不太用到,是因为分析dump是个既耗时又耗机器资源的过程,第二个原因是这个工具比较简陋,没有MAT( Eclipse Memory Analyzer tool)、IBM HeapAnalyzer这些专业和强大。
OpenJDK正在从JDK中废弃HPROF agent 并移除“jhat”工具。这是OpenJDK 9的Java SE平台借助Jigsaw实现模块化的结果,为了准备模块化,起草了多项提议(JEP),并且其中有很多都已经接近完成了。
6、jconsole:JConsole是一个基于JMX的GUI工具,用于连接正在运行的JVM,不过此JVM需要使用可管理的模式启动。简易的JVM可视化工具,其功能被jvisualvm替代。
7、jvisualvm:功能更强大的JVM可视化工具,
jvisualVM所谓多合一虚拟机故障处理工具,有强大的插件扩展功能,通过安装插件扩展支持,jvisualVM可以做到:
a、显示虚拟机进程及进程的配置和环境信息(jps,jinfo);
b、监视应用程序CPU、GC、堆、方法区及线程的信息(jstat、jstack);
c、dump及分析堆转储快照(jmap、jhat);
d、方法级的程序性能分析,找出调用最多,运行时间最长的方法;
8、javap:查看字节码
9、jcmd:在JDK 1.7之后,新增了一个命令行工具jcmd。它是一个多功能工具,可以用来导出堆,查看java进程,导出线程信息,执行GC等。jcmd拥有jmap的大部分功能,Oracle官方建议使用jcmd代替jmap。
1.3.arthas
- 简介 | arthas
- https://github.com/alibaba/arthas/issues/1892
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
Arthas
可以帮助你解决:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到 JVM 的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从 JVM 内查找某个类的实例?
Arthas
支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab
自动补全功能,进一步方便进行问题的定位和诊断。
1.4.jprofile
- YourKit是一个商业化的Java性能分析工具,提供了线程转储分析功能,可以快速定位线程问题,同时还提供了内存和CPU分析功能。
- Java Profiler Features - YourKit
JProfiler是一种Java性能分析器,可以帮助开发人员监视和优化Java应用程序的性能。它提供了一个功能强大的图形用户界面,使开发人员能够实时监视CPU使用情况、内存使用情况、线程和锁状态等信息。JProfiler还具有一些其他功能,例如分析内存泄漏、检测代码覆盖率、监视数据库连接等。
使用JProfiler进行性能分析的一般步骤:
- 下载和安装JProfiler:从JProfiler官方网站下载JProfiler安装程序,并按照提示进行安装。
- 启动JProfiler:在开始菜单或桌面图标中找到JProfiler应用程序,并启动它。
- 创建会话:在JProfiler主界面中,单击“会话”按钮,并选择“创建”会话。在“会话设置”对话框中,选择要监视的Java进程或远程主机,并设置其他选项。
- 配置监视选项:在会话设置中,您可以选择要监视的Java应用程序选项。例如,您可以监视Java应用程序的CPU使用情况、内存使用情况、线程和锁状态等信息。
- 开始监视:在会话设置中,单击“开始”按钮,以开始监视Java应用程序。JProfiler将显示实时数据,并在出现问题时发出警告。
- 分析性能数据:在监视期间,您可以使用JProfiler的图形用户界面查看性能数据。您可以使用各种图表和工具来分析Java应用程序的性能,例如CPU使用率图表、内存使用情况图表、线程和锁状态等。
- 解决问题:根据分析的结果,您可以使用JProfiler提供的各种工具来解决性能问题。例如,您可以修复内存泄漏、优化代码、调整JVM参数等。
- 关闭会话:在解决问题后,您可以关闭JProfiler会话。如果您需要继续监视Java应用程序的性能,可以创建一个新的会话并重复上述步骤。
总之,使用JProfiler可以帮助开发人员更好地了解Java应用程序的性能,并解决性能问题。但是,使用JProfiler需要一定的经验和技能,因此建议您先学习有关JProfiler的相关知识再使用它。
1.5.jar包反编译工具
下载地址:Java Decompiler
JD-GUI和JAD是两个用于反编译Java字节码的工具。它们通常在以下情况下使用:
- 代码调试:当你需要调试Java代码时,可以使用JD-GUI将Java类反编译为可读的源代码,以便进行调试和分析。
- 代码分析:如果你需要对Java类进行深入的分析,例如了解代码结构、方法调用关系等,可以使用JD-GUI来反编译Java类,并查看反编译后的源代码。
- 代码重构:如果你需要修改现有的Java类,可以使用JD-GUI将Java类反编译为可读的源代码,然后进行修改。注意,反编译后的源代码可能不完全与原始源代码相同,因此在进行修改时需要谨慎。
- 辅助学习:如果你是一名Java初学者,可以通过JD-GUI和JAD反编译现有的Java类,了解Java类的结构和实现方式,从而加深对Java语言的理解。
1.6.idea远程debug工具
线上环境最好不要远程debug,因为debug时,会阻塞当前java进程的全部请求。大多数是在测试环境、开发环境。
远程调试(对应IDEA功能:Remote JVM Debug)。远程调试使开发人员能够直接诊断服务器或其它线上进程上的问题,它提供了跟踪线上运行时错误并确定性能瓶颈和问题根源的方法,让你能够像在本地调试一样 Debug 远程服务器。
Ⅰ:Java的远程调试机制:
Java虚拟机提供了远程调试机制,只需要在服务端启动时通过添加JVM参数开启调试服务端口,并且在
客户端使用调试器连接到这个服务端口,就可以实现对远程JVM上程序的调试。
Ⅱ:IntelliJ IDEA远程调试的实现方式:
IDEA利用Java的远程调试机制,在目标JVM上启用调试服务端口,并在IDEA上创建远程调试配置,连接
到目标JVM上的调试服务端口,实现对远程程序的调试和控制。
Ⅲ:远程调试协议:
在远程调试时,客户端和服务端之间通过远程调试协议进行通信。客户端会发送调试命令和断点信息到
服务端口,服务端会执行调试命令并返回相应的结果,通过协议来实现客户端与服务端的交互。
Ⅳ:远程调试的工作原理:
远程调试流程包括以下步骤:
①:启动远程 JVM 并配置调试服务端口;
②:在客户端创建远程调试配置,并连接到目标 JVM 上的调试服务端口;
③:在客户端设置断点和调试命令,并通过远程调试协议发送到服务端口;
④:服务端接收到命令后执行,并返回结果;
⑤:客户端收到结果后,根据调试命令和状态更新调试器界面。
Ⅴ:远程调试的优劣势:
优势:可以直接在目标环境上调试代码,同时也可避免因操作系统等差异导致的问题;
劣势:需要在目标环境上(服务端)开启调试服务端口,同时还需要在客户端设置调试器进行连接,非
常繁琐。
1:服务端添加远程通道
要让远程服务器运行的代码支持远程调试,则服务端启动的时候必须加上特定的 JVM 参数,这些参数是:不同的JDK版本需要设置不同的配置:JDK 9 or later-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:9999JDK 5-8-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9999JDK 1.4.x-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9999JDK 1.3.x or earlier-Xnoagent -Djava.compiler=NONE -Xdebug-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9999这里的9999则是服务端开放的端口,后期客户端IDEA需要连接当前端口进行远程交互和调试。
但是我们需要注意的是,这个9999端口在服务端一定要放开防火墙或者安全组;
具体端口看项目需求;运行服务端jar包程序则如下(JDK 5-8版本):java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9999 ./SwaggerDemo-0.0.1-SNAPSHOT.jar > app.log &
2:客户端连接远程通道设置Edit Configurations来配置信息
备注:服务器代码和本地代码必须一致,否则debug断点无效。
1.7.springbootAdmin
在SpringCloud项目中,部署一个SpringBootAdmin即可通过web页面查看各应用的request、堆、栈等信息。具体实现是SpringCloud的actoator。
用于对 Spring Boot 应用的管理和监控。可以用来监控服务是否健康、是否在线、以及一些jvm数据等等。 Spring Boot Admin 分为服务端(spring-boot-admin-server)和客户端(spring-boot-admin-client),服务端和客户端之间采用 http 通讯方式实现数据交互;单体项目中需要整合 spring-boot-admin-client 才能让应用被监控。 在 SpringCloud 项目中,spring-boot-admin-server 是直接从注册中心抓取应用信息,不需要每个微服务应用整合 spring-boot-admin-client 就可以实现应用的管理和监控。
主要的功能点有:
- 显示应用程序的监控状态
- 应用程序上下线监控
- 查看 JVM,线程信息
- 可视化的查看日志以及下载日志文件
- 动态切换日志级别
- Http 请求信息跟踪
详细配置如下
<!--用于检查系统的监控情况--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--Spring Boot Admin Server监控服务端--><dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.3.1</version></dependency><!--增加安全防护,防止别人随便进--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>启动类开启admin@EnableAdminServer登录配置
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {private final String adminContextPath;public SecuritySecureConfig(AdminServerProperties adminServerProperties) {this.adminContextPath = adminServerProperties.getContextPath();}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 登录成功处理类SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();successHandler.setTargetUrlParameter("redirectTo");successHandler.setDefaultTargetUrl(adminContextPath + "/");http.authorizeRequests()//静态文件允许访问.antMatchers(adminContextPath + "/assets/**").permitAll()//登录页面允许访问.antMatchers(adminContextPath + "/login", "/css/**", "/js/**", "/image/*").permitAll()//其他所有请求需要登录.anyRequest().authenticated().and()//登录页面配置,用于替换security默认页面.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()//登出页面配置,用于替换security默认页面.logout().logoutUrl(adminContextPath + "/logout").and().httpBasic().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).ignoringAntMatchers("/instances","/actuator/**");}
}yml配置
server:port: 9111
spring:boot:admin:ui:title: HMB服务监控中心client:instance:metadata:tags:environment: local#要获取的client的端点信息probed-endpoints: health,env,metrics,httptrace:trace,threaddump:dump,jolokia,info,logfile,refresh,flyway,liquibase,heapdump,loggers,auditeventsmonitor: # 监控发送请求的超时时间default-timeout: 20000security: # 设置账号密码user:name: adminpassword: admin
# 服务端点详细监控信息
management: trace:http:enabled: trueendpoints:web:exposure:include: "*"endpoint:health:show-details: always启动项目
访问 http://ip:端口,如我的http://localhost:9111,账号密码都是admin(上面的security配的)
多大
1.8.JOL(即Java Object Layout)
JOL(即Java Object Layout):OpenJDK提供的库,用于查看Java对象的内存布局,这个很有用,可以借助它来跟踪锁升级等过程。只需要引入Maven即可使用。
//引入依赖<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.16</version></dependency>//代码class TTTT {public static void main(String[] args) {System.err.println(ClassLayout.parseInstance(new Person()).toPrintable());System.err.println(ClassLayout.parseClass(Person.class).toPrintable());}
}class Person {private int age = 1;private String name = "zhangsan";
}//代码执行结果
com.marchon.learning.Person object internals:
OFF SZ TYPE DESCRIPTION VALUE0 8 (object header: mark) 0x0000005e4c804101 (hash: 0x5e4c8041; age: 0)8 4 (object header: class) 0xf8010dd912 4 int Person.age 116 4 java.lang.String Person.name (object)20 4 (object alignment gap)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
2.分析工具使用
2.1 jps和jinfo
常用命令: jps (输出java进程号pid)、 jps -l (输出java进程号和详细的jar信息) 、 jinfo pid(输出 java进程系统参数和jvm参数)、jinfo -flags pid (指输出jvm参数信息)
2.2 jstack
jstack 是 JDK 自带的一种堆栈跟踪工具,可用于生成 JVM 当前时刻的线程快照。线程快照是当前 JVM 内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过 jstack 来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果 java 程序崩溃生成 core 文件,jstack 工具可以用来获得 core 文件的 java stack 和 native stack 的信息,从而可以知道 java 程序是如何崩溃和在程序何处发生问题。另外,jstack 工具还可以 attach 到正在运行的 java 程序中,看到当时运行的 java 程序的 java stack 和 native stack的信息, 如果现在运行的 java 程序呈现 hung 的状态,jstack 是非常有用的。
简而言之,jstack 主要用来查看 Java 线程的调用堆栈,可以用来分析线程问题(如死锁、死循环、CPU 占用过高)。
- -F:当正常输出的请求不被响应时,强制输出线程堆栈
- -m:如果调用到本地方法的话,加上此参数可以显示本地方法的堆栈
- -l:最常用的一个参数,除堆栈外,显示关于锁的附加信息,在发生死锁时可以用 jstack -l pid 来观察锁持有情况
把 jstack 的输出重定向到文件中,就可以分析了。
// 比如
jstack -l <pid> >> thread.log
java中锁的实现是通过monitor来实现的,它可以看成是对象或者 Class 的锁。每一个对象都有,也仅有一个 monitor。下图描述了线程和 Monitor 之间的关系,以及线程的状态转换图:
- 进入区(Entry Set):表示线程通过 synchronized 要求获取对象的锁。如果对象未被锁住,则变为拥有者,否则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
- 拥有者(The Owner):表示某一线程成功竞争到对象锁。
- 等待区(Wait Set):表示线程通过对象的 wait 方法,释放对象的锁,并在等待区等待被唤醒。
从图中可以看出,一个 Monitor 在某个时刻,只能被一个线程拥有,该线程就是 Active Thread,而其它线程都是 Waiting Thread,分别在两个队列 Entry Set 和 Wait Set 里面等候。在 Entry Set 中等待的线程状态是 Waiting for monitor entry,而在 Wait Set 中等待的线程状态是 “in Object.wait()”。
使用 jstack 分析死锁步骤非常简单:
- jps 获取 pid
- jstack -l pid 打印堆栈信息
- 分析堆栈信息,一般来说 Java-level 的死锁,jstack 能自动检测出来。
比如下面这段 jstack 打印的堆栈信息,就是 jstack 自动检测出了一个 Java-level 死锁:
- Thread-0 锁住了<0x00000007d6aa2c98>,尝试获取 <0x00000007d6aa2ca8> 的锁
- Thread-1 锁住了<0x00000007d6aa2ca8>,尝试获取 <0x00000007d6aa2c98> 的锁
Found one Java-level deadlock:
=============================
"Thread-1":waiting to lock monitor 0x00007f0134003ae8 (object 0x00000007d6aa2c98, a java.lang.Object),which is held by "Thread-0"
"Thread-0":waiting to lock monitor 0x00007f0134006168 (object 0x00000007d6aa2ca8, a java.lang.Object),which is held by "Thread-1"Java stack information for the threads listed above:
===================================================
"Thread-1":at javaCommand.DeadLockclass.run(JStackDemo.java:40)- waiting to lock <0x00000007d6aa2c98> (a java.lang.Object)- locked <0x00000007d6aa2ca8> (a java.lang.Object)at java.lang.Thread.run(Thread.java:745)
"Thread-0":at javaCommand.DeadLockclass.run(JStackDemo.java:27)- waiting to lock <0x00000007d6aa2ca8> (a java.lang.Object)- locked <0x00000007d6aa2c98> (a java.lang.Object)at java.lang.Thread.run(Thread.java:745)Found 1 deadlock.
需要注意的是,jstack 只能自动检测 Java 线程间的死锁,不能检测到其它类型的线程状态,比如本地线程或者操作系统线程的状态。
如果要分析本地线程或者操作系统线程是否出现了死锁,可以在使用 jstack 时加上 -m 参数,把本地线程堆栈一起打印起来进行分析。
2.2.1 jstack分析锁信息和死锁
使用 jstack 查看线程堆栈信息时可能会看到的线程的几种状态:
- New:创建后尚未启动的线程处于这种状态,不会出现在Dump中。
- RUNNABLE:包括Running和Ready。线程开启start()方法,会进入该状态,在虚拟机内执行的。
- Waiting:无限的等待另一个线程的特定操作。
- Timed Waiting:有时限的等待另一个线程的特定操作。
- Blocked:在程序等待进入同步区域的时候,线程将进入这种状态,在等待监视器锁。
- Terminated:已终止线程的线程状态,线程已经结束执行。
Dump 文件的线程状态一般其实就以下3种:
- RUNNABLE,线程处于执行中
- BLOCKED,线程被阻塞
- WAITING,线程正在等待
常见 dump 内容
- locked <地址> 目标:申请对象锁成功,监视器的拥有者。
at oracle.jdbc.driver.PhysicalConnection.prepareStatement
- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement
- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)
at com.jiuqi.dna.core.internal.db.datasource.PooledConnection.prepareStatement
- waiting to lock <地址> 目标:申请对象锁未成功,在 Entry Set 等待。
// 一个线程锁住某对象,大量其他线程在该对象上等待:
"blocker" runnable
java.lang.Thread.State: RUNNABLE
at com.jiuqi.hcl.javadump.Blocker$1.run(Blocker.java:23)
- locked <0x00000000eb8eff68> (a java.lang.Object)
"blockee-11" waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
"blockee-86" waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
- waiting on <地址> 目标:释放对象锁,在等待区等待被唤醒。
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000da2defb0> (a WorkingThread)
at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo
- locked <0x00000000da2defb0> (a WorkingThread)
at com.jiuqi.dna.core.impl.WorkingThread.run
2.2.2jstack分析cpu占用
cpu飙高分析流程:稍后写个case复现一把。
1.top 查看占用 CPU 较高的进程,可以发现 pid 为 21340 的进程 CPU 占用较高。
2.top -Hp pid 可以查看该进程下各个线程的 CPU 使用情况,可以发现线程21350的 CPU 占用较高
3.jstack -l pid >> dump.log 将线程堆栈信息保存下来
4.分析堆栈信息,thread dump 中,每个线程对应一个十六进制的 nid(native thread id),将 21350 转成十六进制 5366 然后 grep 查看相关信息即可:查看线程信息附近线程状态,重点关注Blocked
2.3jstat
jstat 是 JDK 自带的一个命令行工具,全称为 Java Virtual Machine statistics monitoring tool,可以用来监视和分析 Java 应用程序的内存使用和性能情况。jstat 命令可以显示有关 Java 堆和非堆内存使用情况、类加载、垃圾回收、线程和编译器等方面的信息。
jstat [ generalOption | outputOptions vmid [ interval[s|ms] [count] ] ]参数说明:generalOption:一般选项,用于设置 jstat 命令的全局行为。可以是以下选项之一:
-class:显示类加载情况。
-compiler:显示JIT编译器统计信息。
-gc:显示垃圾回收统计信息。
-gccapacity:显示垃圾回收堆内存使用情况。
-gcmetacapacity:显示垃圾回收非堆内存使用情况。
-gcnew:显示新生代垃圾回收统计信息。
-gcnewcapacity:显示新生代垃圾回收堆内存使用情况。
-gcold:显示老年代垃圾回收统计信息。
-gcoldcapacity:显示老年代垃圾回收堆内存使用情况。
-gcutil:显示垃圾回收堆内存使用情况总览。
-printcompilation:显示 JIT 编译器编译情况。
outputOptions:输出选项,用于设置 jstat 命令的输出格式。可以是以下选项之一:
-t:输出时间戳。
-h:输出帮助信息。
-J:输出完整的 JVM 内部信息。
vmid:Java 虚拟机进程 ID 或进程名。
interval:指定采样间隔时间,默认单位是毫秒。可以使用 s 或 ms 后缀指定单位,例如 10s 或 500ms。
count:指定采样次数,默认是无限次。
常用命令
jstat -class pid 显示加载class的数量,及所占空间等信息:
显示列名 | 具体描述 |
---|---|
Loaded | 装载的类的数量 |
Bytes | 装载类所占用的字节数 |
Unloaded | 卸载类的数量 |
Bytes | 卸载类的字节数 |
Time | 装载和卸载类所花费的时间 |
jstat -compiler pid 显示VM实时编译的数量等信息:
显示列名 | 具体描述 |
---|---|
Compiled | 编译任务执行数量 |
Failed | 编译任务执行失败数量 |
Invalid | 编译任务执行失效数量 |
Time | 编译任务消耗时间 |
FailedType | 最后一个编译失败任务的类型 |
FailedMethod | 最后一个编译失败任务所在的类及方法 |
jstat -gc pid 可以显示gc的信息,查看gc的次数,及时间:
显示列名 | 具体描述 |
---|---|
S0C | 年轻代中第一个survivor(幸存区)的容量 (字节) |
S1C | 年轻代中第二个survivor(幸存区)的容量 (字节) |
S0U | 年轻代中第一个survivor(幸存区)目前已使用空间 (字节) |
S1U | 年轻代中第二个survivor(幸存区)目前已使用空间 (字节) |
EC | 年轻代中 Eden(伊甸园)的容量 (字节) |
EU | 年轻代中 Eden(伊甸园)目前已使用空间 (字节) |
OC | 老年代的容量 (字节) |
OU | 老年代目前已使用空间 (字节) |
PC | Perm(持久代)的容量 (字节) |
PU | Perm(持久代)目前已使用空间 (字节) |
YGC | 从应用程序启动到采样时年轻代中 gc 次数 |
YGCT | 从应用程序启动到采样时年轻代中 gc 所用时间(s) |
FGC | 从应用程序启动到采样时老年代(full gc) gc 次数 |
FGCT | 从应用程序启动到采样时老年代(full gc) gc 所用时间(s) |
GCT | 从应用程序启动到采样时 gc 用的总时间(s) |
jstat -gccapacity pid 显示 VM 内存中三代(young, old, perm)对象的使用和占用大小:
显示列名 | 具体描述 |
---|---|
NGCMN | 年轻代(young)中初始化(最小)的大小(字节) |
NGCMX | 年轻代(young)的最大容量 (字节) |
NGC | 年轻代(young)中当前的容量 (字节) |
S0C | 年轻代中第一个 survivor(幸存区)的容量 (字节) |
S1C | 年轻代中第二个 survivor(幸存区)的容量 (字节) |
EC | 年轻代中 Eden(伊甸园)的容量 (字节) |
OGCMN | 老年代中初始化(最小)的大小 (字节) |
OGCMX | 老年代的最大容量(字节) |
OGC | 老年代当前新生成的容量 (字节) |
OC | 老年代的容量 (字节) |
PGCMN | perm 代中初始化(最小)的大小 (字节) |
PGCMX | perm 代的最大容量 (字节) |
PGC | perm 代当前新生成的容量 (字节) |
PC | perm(持久代)的容量 (字节) |
YGC | 从应用程序启动到采样时年轻代中 gc 次数 |
FGC | 从应用程序启动到采样时老年代(full gc) gc 次数 |
jstat -gcutil pid 统计 gc 信息:
显示列名 | 具体描述 |
---|---|
S0 | 年轻代中第一个 survivor(幸存区)已使用的占当前容量百分比 |
S1 | 年轻代中第二个 survivor(幸存区)已使用的占当前容量百分比 |
E | 年轻代中 Eden(伊甸园)已使用的占当前容量百分比 |
O | 老年代已使用的占当前容量百分比 |
P | perm 代已使用的占当前容量百分比 |
YGC | 从应用程序启动到采样时年轻代中 gc 次数 |
YGCT | 从应用程序启动到采样时年轻代中 gc 所用时间(s) |
FGC | 从应用程序启动到采样时老年代(full gc) gc 次数 |
FGCT | 从应用程序启动到采样时老年代(full gc) gc 所用时间(s) |
GCT | 从应用程序启动到采样时 gc 用的总时间(s) |
jstat -gccause pid 1000 10 同gcutil 多了一个gc (打印10次,每次间隔1000ms)
2.4jmap和jcmd
jmap 是 JDK 自带的一个命令行工具,可以用于生成 Java Heap Dump 文件,以及查看 Java 进程中的内存使用情况。
jmap [option] <pid>
jmap [option] <executable (to connect to a core file)
jmap [option] [server_id@] (to connect to remote debug server)option:命令选项,常用选项如下:-heap:打印 Java 堆概要信息,包括使用的 GC 算法、堆配置参数和各代中堆内存使用情况;
-histo[:live]: 打印 Java 堆中对象直方图,通过该图可以获取每个 class 的对象数目,占用内存大小和类全名信息,带上 :live,则只统计活着的对象;
-permstat 打印永久代统计信息;
-finalizerinfo 打印等待回收的对象信息
-dump: 以 hprof 二进制格式将 Java 堆信息输出到文件内,该文件可以用 JProfiler、VisualVM 或 jhat 等工具查看;
dump-options 选项:live 只输出活着的对象,不指定则输出堆中所有对象
format=b 指定输出格式为二进制
file= 指定文件名及文件存储位置,例如:jmap -dump:live,format=b,file=D:\heap.bin
-F 与-dump: 或 -histo 一起使用,当没有响应时,强制执行;注意:不支持live子选项
pid:进程id
- 查看大对象:
jmap -histo <pid>|less
- 查看对象数最多的对象,并按降序排序输出:
jmap -histo <pid>|grep 关键字|sort -k 2 -g -r|less
- 查看占用内存最多的对象,并按降序排序输出:
jmap -histo <pid>|grep 关键字|sort -k 3 -g -r|less
查看大对象jmap -histo pid
jmap -histo:live pid 统计 heap 中所有生存的对象的情况, 这个命令会先触发 gc 再统计:
jmap -dump:live,format=b,file=a.log pid
执行这个命令,JVM 会将整个 heap 的信息 dump 到一个文件,heap 如果比较大的话会导致这个过程比较耗时,并且执行的过程中为了保证 dump 的信息是可靠的会暂停应用。
该命令通常用来分析内存泄漏 OOM,通常做法是:
- 首先配置 JVM 启动参数,让 JVM 在遇到 OutOfMemoryError 时自动生成 Dump 文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path
- 使用命令 Dump Heap 信息
jmap -dump:format=b,file=/path/heap.bin pid
- 使用 MAT 分析工具,如 jhat 命令分析 hprof 文件
2.5jhat
jhat 全称为 Java Virtual Machine Heap Analysis Tool,即虚拟机堆转储快照分析工具。jhat 用于分析 heapdump 文件,它会建立一个HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果。 jhat 一般与 jmap 搭配使用,用于分析 jmap 生成的堆转储快照。jhat 是一个命令行工具,使用起来比较简便,但功能也相对简陋。如果条件允许的话,建议使用 JProfiler 或者 IBM HeapAnalyzer 等功能更强大的工具来分析 heapdump 文件。
jhat [options] heap-dump-fileoption 具体选项及作用如下:-J< flag >:因为 jhat 命令实际上会启动一个 JVM 来执行,通过 -J 可以在启动 JVM 时传入一些启动参数。例如,-J-Xmx512m 指定运行 jhat 的 JVM 使用的最大堆内存为 512 MB。 如果需要使用多个 JVM 启动参数,则传入多个 -Jxxxxxx。
-stack false|true:关闭跟踪对象分配调用堆栈。如果分配位置信息在堆转储中不可用,则必须将此标志设置为 false。默认值为 true。
-refs false|true:关闭对象引用跟踪。默认情况下,返回的指针是指向其他特定对象的对象,如反向链接或输入引用(referrers or incoming references),,会统计/计算堆中的所有对象。
-port port-number:设置 jhat HTTP server 的端口号,默认值 7000。
-exclude exclude-file:指定对象查询时需要排除的数据成员列表文件。 例如,如果文件列出了 java.lang.String.value,那么当从某个特定对象 Object o 计算可达的对象列表时,引用路径涉及 java.lang.String.value 的都会被排除。
-baseline exclude-file:指定一个基准堆转储(baseline heap dump)。 在两个 heap dump 文件中有相同 object ID 的对象会被标记为不是新的(marked as not being new),其他对象被标记为新的(new)。在比较两个不同的堆转储时很有用。
-debug int:设置 debug 级别,0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息。
-version:启动后只显示版本信息就退出。
2.6 jvisualvm
最后说jvisualvm,因为jvisualvm是对前面jps、jinfo、jstack、jstat、jmap、jhat的汇总,集上面之大成,并提供了可视化的界面;还可以监控远程Java服务;支持监控JMX。安装完插件比JConsole的功能还要完善。JVisualVM比JConsole更强大:支持对CPU、内存运行进行采样、配置。推荐用JVisualVM。
jconsole都不能保存连接信息,每次都要输入
安装插件
安装成功后的效果
JAVA Dump:
JAVA Dump就是虚拟机运行时的快照,将虚拟机运行时的状态和信息保存到文件中,包括:
线程dump:包含所有线程的运行状态,纯文本格式
堆dump:包含所有堆对象的状态,二进制格式
相关文章:

Java web应用性能分析之【java进程问题分析工具】
Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 前面大概讲了java进程问题分析流程,这里再小结一下分析工具,后面也会小结一下java进程问题分析定位。 1.分析工具 1.1.linux命令工具 参考:Java web应用性能分析之【Linux服务器性…...

02-2.3.2_2 单链表的查找
喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。 此外,《程序员必备技能》专栏和《程序员必备工具》专栏(该专栏暂未开设)日后会逐步更新,感兴趣的小伙伴可以点一下订阅、收藏、关注! 谢…...

设计模式(十四)行为型模式---访问者模式(visitor)
文章目录 访问者模式简介分派的分类什么是双分派?结构UML图具体实现UML图代码实现 优缺点 访问者模式简介 访问者模式(visitor pattern)是封装一些作用于某种数据结构中的元素的操作,它可以在不改变这个数据结构(实现…...

【Matplotlib作图-3.Ranking】50 Matplotlib Visualizations, Python实现,源码可复现
目录 03 Ranking 3.0 Prerequisite 3.1 有序条形图(Ordered Bar Chart) 3.2 棒棒糖图(Lollipop Chart) 3.3 点图(Dot Plot) 3.4 斜率图(Slope Chart) 3.5 杠铃图(Dumbbell Plot) References 03 Ranking 3.0 Prerequisite Setup.py # !pip install brewer2mpl import n…...

加入不正确的位置编码会破坏掉原本的信息吗?
会 位置编码的作用 在Transformer中,位置编码的主要作用是让模型感知输入序列中各个词的位置。因为Transformer完全依赖自注意力机制,它本身并没有序列信息,位置编码的引入就是为了补充这一点。 加法操作的合理性 位置编码通过加法操作与…...

区块链合约开发流程
区块链合约开发,尤其是以太坊智能合约开发,是一个多步骤的过程,从需求分析到部署和维护,每一步都需要仔细规划和执行。以下是详细的开发流程。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合…...

建筑企业有闲置资质怎么办?
如果建筑企业拥有闲置资质,可以考虑以下几种方式来充分利用这些资质: 1. 租赁或转让资质: 将闲置的建筑资质租赁给其他企业或个人使用,或者通过转让的方式将资质出售给有需要的企业或个人。 2. 提供咨询服务: 利用建…...

Java开发-特殊文本文件,日志技术
目录 01.特殊文件,日志技术概述 02.特殊文件:Properties属性文件 编辑Properties案例 特殊文件:XML文件 XML的作用和应用场景 读取XML文件中的数据 XML的生成 约束XML文件的编写[了解] 日志技术 日志技术的体系 编辑 编辑 Logback日志框架的概述 Logback快…...

Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践
系列文章目录 Django入门全攻略:从零搭建你的第一个Web项目Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解Django ORM深度游ÿ…...

无人机路径规划:基于鸽群优化算法PIO的无人机三维路径规划MATLAB代码
一、无人机模型介绍 无人机三维航迹规划_无人机航迹规划-CSDN博客 二、部分代码 close all clear clc warning (off) global model global gca1 gca2 gca3 gca4 model CreateModel(); % Create search map and parameters load(BestPosition5.mat); load(ConvergenceCurve5…...

ArcGIS属性域和子类型
01 属性域 道路的车道数值是小于10的。在编辑道路的此属性时,为了限制其值在10以内,可以使用属性域。当输入数据超过10时,就会限制输入。 限制输入这个功能是Pro特有的,在ArcMap中输入超出限制的值也是合法的,需要手动…...

电子电器架构 --- 什么是域控制器?
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...

链表头部插入结点
Linked List Inserting a node at beginning #include<stdlib.h>//为了用malloc #include<stdio.h> struct node {int data;struct node* next;//在cpp中可以只写 Node *Link;//为了表意明确,Link也经常被命名为next }; struct node* head…...

k8s集群修改apiserver的ip地址
有时候由于服务器的调整,导致ip的的变化,k8s集群的api大管家的ip变动会导致kubectl的接口都无法正常使用,这是只需要将k8s主节点配置文件的ip替换即可。 例如无需要将原来的192.168.146.202的ip替换成192.168.85.202,执行一下操作…...

C语言编程技巧:深度挖掘与高效实践
C语言编程技巧:深度挖掘与高效实践 在编程的世界里,C语言以其高效、灵活和底层控制能力强等特点,一直备受开发者们的青睐。然而,要想真正掌握C语言的精髓,并编写出高效、健壮的代码,却并非易事。本文将从四…...

十_信号14 - system()
意思是 应在在调用 system() 函数前 阻塞 SIGCHLD 信号,否则,子进程结束的时候,系统会向该进程(父)发送 SIGCHLD信号,则该进程认为是自己的一个子进程结束了,于是调用 wait函数获取子进程的终止状态。这本来是正常的操…...

【Python网络爬虫】详解python爬虫中URL资源抓取
🔗 运行环境:PYTHON 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 #### 防伪水印——左手の明天 #### 💗 大家好🤗ᾑ…...

AI办公自动化:用kimi批量提取音频中的标题并重命名
很多音频文件,文件名很乱,需要根据音频信息中的标题聪明吗 在kimi中输入提示词: 你是一个Python编程专家,一步步的思考,完成以下脚本的撰写: 打开文件夹:E:\有声\a16z播客 读取里面所有的mp3格…...

flyfish3.0.0配置避坑
1.基础环境准备篇 doc/01-基础环境准备篇.md 云智慧/FlyFish - Gitee.com 使用教程里给出的java环境时,可以显示java版本,但是不能显示Maven的版本 改为: export NODE_HOME/usr/local/node/node-v14.19.3-linux-x64 export PATH$NODE_HOME…...

Spring (33)CSRF(跨站请求伪造)保护
跨站请求伪造(CSRF)是一种常见的网络攻击手段,它允许攻击者在不知情的用户浏览器中发起恶意请求。这种攻击利用了网站对用户浏览器的信任。如果用户在浏览器中已经登录了一个网站,攻击者就可以构造一个请求,这个请求能…...

【一刷《剑指Offer》】面试题 29:数组中出现次数超过一半的数字
力扣对应题目链接:169. 多数元素 - 力扣(LeetCode) 牛客对应题目链接:数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com) 核心考点 : 数组使用,简单算法的设计。 一、《剑指Offer》对应内容 二…...

vx小程序初学
小程序初学 在我还没接触到微信小程序之前,通常使用轮播要么手写或使用swiper插件去实现,当我接触到微信小程序之后,我看到了微信小程序的强大之处,让我为大家介绍一下吧! swiper与swiper-item一起使用可以做轮播图 …...

vue 笔记01
目录 01 vuejs中属性的基本使用 02 v-show指令的使用 03 v-if 指令的使用 04 v-for指令的使用 05 v-model 指令 06 template模板标签 07 v-on事件的绑定指令 08 事件中的event对象 01 vuejs中属性的基本使用 {{ }} 叫做mustache模板语法 双花括号 小胡子语法 双花括号…...

开发电商系统的技术选型
开发电商系统是一个复杂的任务,需要全面的技术选型来确保系统的稳定性、可扩展性和性能。本文将详细探讨在开发电商系统时涉及的各方面技术选型,包括架构设计、前端技术、后端技术、数据库选择、缓存策略、安全性、支付系统、日志和监控、以及自动化运维…...

C++STL---vector常见用法
C STL中的vector vector是C标准模板库(STL)中最常用的序列容器之一,它是一个动态数组,能够存储任意类型的对象(如整数、字符串等)。vector的主要优点是提供了快速的随机访问,同时还能够动态地调…...

linux文件共享之samba
1.介绍 Samba是一个开源文件共享服务,可以使linux与windows之间进行文件共享,可以根据不同人员调整共享设置以及权限管理。 2.安装 一个命令就OK了:yum install -y samba [rootansible01 ~]# yum install -y samba 已加载插件:l…...

端午传统食品创意营销方案
端午传统食品创意营销方案 目 录 一、市场营销环境分析 1 (一)历史记载 1 (二)粽叶的象征 1 (三)粽子文化 1 (四)竞争分析 2 (五)粽子当今发展 4 二、产品创…...

制作ChatPDF之Elasticsearch8.13.4搭建(一)
Elasticsearch8.x搭建 在Windows系统上本地安装Elasticsearch的详细步骤如下: 1. 下载Elasticsearch 访问 Elasticsearch下载页面。选择适用于Windows的版本8.13.4,并下载ZIP文件。 2. 解压文件 下载完成后,找到ZIP文件(例如…...

一种最大重叠离散小波包特征提取和支持向量机的ECG心电信号分类方法(MATLAB 2018)
目前小波分析算法常采用Mallat快速算法。该算法由与滤波器卷积、隔点采样和隔点插零等三个环节组成。由于实际使用的滤波器并不具有理想频域特性,使得在标准二进小波算法中存在着频率混叠和小波系数失真等缺点,在标准二进小波包算法中还存在频带错乱现象…...

德勤:中国、印度等对ChatGPT等生成式AI应用,处领先地位
全球四大会计事务所之一的德勤(Deloitte)在官网发布了一份,名为《Generative AI in Asia Pacific: Young employees lead as employers play catch-up》的深度调查报告。 主要查看中国、澳大利亚、印度、日本、新加坡、韩国、中国台湾等亚太…...