当前位置: 首页 > news >正文

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可以帮助你解决:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到 JVM 的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?
  8. 怎样直接从 JVM 内查找某个类的实例?

  Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

        1.4.jprofile
  • YourKit是一个商业化的Java性能分析工具,提供了线程转储分析功能,可以快速定位线程问题,同时还提供了内存和CPU分析功能。
  • Java Profiler Features - YourKit

        JProfiler是一种Java性能分析器,可以帮助开发人员监视和优化Java应用程序的性能。它提供了一个功能强大的图形用户界面,使开发人员能够实时监视CPU使用情况、内存使用情况、线程和锁状态等信息。JProfiler还具有一些其他功能,例如分析内存泄漏、检测代码覆盖率、监视数据库连接等。

        使用JProfiler进行性能分析的一般步骤:

  1. 下载和安装JProfiler:从JProfiler官方网站下载JProfiler安装程序,并按照提示进行安装。
  2. 启动JProfiler:在开始菜单或桌面图标中找到JProfiler应用程序,并启动它。
  3. 创建会话:在JProfiler主界面中,单击“会话”按钮,并选择“创建”会话。在“会话设置”对话框中,选择要监视的Java进程或远程主机,并设置其他选项。
  4. 配置监视选项:在会话设置中,您可以选择要监视的Java应用程序选项。例如,您可以监视Java应用程序的CPU使用情况、内存使用情况、线程和锁状态等信息。
  5. 开始监视:在会话设置中,单击“开始”按钮,以开始监视Java应用程序。JProfiler将显示实时数据,并在出现问题时发出警告。
  6. 分析性能数据:在监视期间,您可以使用JProfiler的图形用户界面查看性能数据。您可以使用各种图表和工具来分析Java应用程序的性能,例如CPU使用率图表、内存使用情况图表、线程和锁状态等。
  7. 解决问题:根据分析的结果,您可以使用JProfiler提供的各种工具来解决性能问题。例如,您可以修复内存泄漏、优化代码、调整JVM参数等。
  8. 关闭会话:在解决问题后,您可以关闭JProfiler会话。如果您需要继续监视Java应用程序的性能,可以创建一个新的会话并重复上述步骤。

        总之,使用JProfiler可以帮助开发人员更好地了解Java应用程序的性能,并解决性能问题。但是,使用JProfiler需要一定的经验和技能,因此建议您先学习有关JProfiler的相关知识再使用它。

        1.5.jar包反编译工具

        下载地址:Java Decompiler

        JD-GUI和JAD是两个用于反编译Java字节码的工具。它们通常在以下情况下使用:

  1. 代码调试:当你需要调试Java代码时,可以使用JD-GUI将Java类反编译为可读的源代码,以便进行调试和分析。
  2. 代码分析:如果你需要对Java类进行深入的分析,例如了解代码结构、方法调用关系等,可以使用JD-GUI来反编译Java类,并查看反编译后的源代码。
  3. 代码重构:如果你需要修改现有的Java类,可以使用JD-GUI将Java类反编译为可读的源代码,然后进行修改。注意,反编译后的源代码可能不完全与原始源代码相同,因此在进行修改时需要谨慎。
  4. 辅助学习:如果你是一名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 就可以实现应用的管理和监控。

        主要的功能点有:

  1.                 显示应用程序的监控状态
  2.                 应用程序上下线监控
  3.                 查看 JVM,线程信息
  4.                 可视化的查看日志以及下载日志文件
  5.                 动态切换日志级别
  6.                 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 分析死锁步骤非常简单:
  1. jps 获取 pid
  2. jstack -l pid 打印堆栈信息
  3. 分析堆栈信息,一般来说 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老年代目前已使用空间 (字节)
PCPerm(持久代)的容量 (字节)
PUPerm(持久代)目前已使用空间 (字节)
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老年代的容量 (字节)
PGCMNperm 代中初始化(最小)的大小 (字节)
PGCMXperm 代的最大容量 (字节)
PGCperm 代当前新生成的容量 (字节)
PCperm(持久代)的容量 (字节)
YGC从应用程序启动到采样时年轻代中 gc 次数
FGC从应用程序启动到采样时老年代(full gc) gc 次数

jstat -gcutil pid 统计 gc 信息:

显示列名具体描述
S0年轻代中第一个 survivor(幸存区)已使用的占当前容量百分比
S1年轻代中第二个 survivor(幸存区)已使用的占当前容量百分比
E年轻代中 Eden(伊甸园)已使用的占当前容量百分比
O老年代已使用的占当前容量百分比
Pperm 代已使用的占当前容量百分比
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进程问题分析流程&#xff0c;这里再小结一下分析工具&#xff0c;后面也会小结一下java进程问题分析定位。 1.分析工具 1.1.linux命令工具 参考&#xff1a;Java web应用性能分析之【Linux服务器性…...

02-2.3.2_2 单链表的查找

喜欢《数据结构》部分笔记的小伙伴可以订阅专栏&#xff0c;今后还会不断更新。 此外&#xff0c;《程序员必备技能》专栏和《程序员必备工具》专栏&#xff08;该专栏暂未开设&#xff09;日后会逐步更新&#xff0c;感兴趣的小伙伴可以点一下订阅、收藏、关注&#xff01; 谢…...

设计模式(十四)行为型模式---访问者模式(visitor)

文章目录 访问者模式简介分派的分类什么是双分派&#xff1f;结构UML图具体实现UML图代码实现 优缺点 访问者模式简介 访问者模式&#xff08;visitor pattern&#xff09;是封装一些作用于某种数据结构中的元素的操作&#xff0c;它可以在不改变这个数据结构&#xff08;实现…...

【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中&#xff0c;位置编码的主要作用是让模型感知输入序列中各个词的位置。因为Transformer完全依赖自注意力机制&#xff0c;它本身并没有序列信息&#xff0c;位置编码的引入就是为了补充这一点。 加法操作的合理性 位置编码通过加法操作与…...

区块链合约开发流程

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

建筑企业有闲置资质怎么办?

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

Java开发-特殊文本文件,日志技术

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

Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…...

无人机路径规划:基于鸽群优化算法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的。在编辑道路的此属性时&#xff0c;为了限制其值在10以内&#xff0c;可以使用属性域。当输入数据超过10时&#xff0c;就会限制输入。 限制输入这个功能是Pro特有的&#xff0c;在ArcMap中输入超出限制的值也是合法的&#xff0c;需要手动…...

电子电器架构 --- 什么是域控制器?

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

链表头部插入结点

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

k8s集群修改apiserver的ip地址

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

C语言编程技巧:深度挖掘与高效实践

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

十_信号14 - system()

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

【Python网络爬虫】详解python爬虫中URL资源抓取

&#x1f517; 运行环境&#xff1a;PYTHON &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…...

AI办公自动化:用kimi批量提取音频中的标题并重命名

很多音频文件&#xff0c;文件名很乱&#xff0c;需要根据音频信息中的标题聪明吗 在kimi中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;一步步的思考&#xff0c;完成以下脚本的撰写&#xff1a; 打开文件夹&#xff1a;E:\有声\a16z播客 读取里面所有的mp3格…...

flyfish3.0.0配置避坑

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

Spring (33)CSRF(跨站请求伪造)保护

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

【一刷《剑指Offer》】面试题 29:数组中出现次数超过一半的数字

力扣对应题目链接&#xff1a;169. 多数元素 - 力扣&#xff08;LeetCode&#xff09; 牛客对应题目链接&#xff1a;数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com) 核心考点 &#xff1a; 数组使用&#xff0c;简单算法的设计。 一、《剑指Offer》对应内容 二…...

vx小程序初学

小程序初学 在我还没接触到微信小程序之前&#xff0c;通常使用轮播要么手写或使用swiper插件去实现&#xff0c;当我接触到微信小程序之后&#xff0c;我看到了微信小程序的强大之处&#xff0c;让我为大家介绍一下吧&#xff01; 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模板语法 双花括号 小胡子语法 双花括号…...

开发电商系统的技术选型

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

C++STL---vector常见用法

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

linux文件共享之samba

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

端午传统食品创意营销方案

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

制作ChatPDF之Elasticsearch8.13.4搭建(一)

Elasticsearch8.x搭建 在Windows系统上本地安装Elasticsearch的详细步骤如下&#xff1a; 1. 下载Elasticsearch 访问 Elasticsearch下载页面。选择适用于Windows的版本8.13.4&#xff0c;并下载ZIP文件。 2. 解压文件 下载完成后&#xff0c;找到ZIP文件&#xff08;例如…...

一种最大重叠离散小波包特征提取和支持向量机的ECG心电信号分类方法(MATLAB 2018)

目前小波分析算法常采用Mallat快速算法。该算法由与滤波器卷积、隔点采样和隔点插零等三个环节组成。由于实际使用的滤波器并不具有理想频域特性&#xff0c;使得在标准二进小波算法中存在着频率混叠和小波系数失真等缺点&#xff0c;在标准二进小波包算法中还存在频带错乱现象…...

德勤:中国、印度等对ChatGPT等生成式AI应用,处领先地位

全球四大会计事务所之一的德勤&#xff08;Deloitte&#xff09;在官网发布了一份&#xff0c;名为《Generative AI in Asia Pacific: Young employees lead as employers play catch-up》的深度调查报告。 主要查看中国、澳大利亚、印度、日本、新加坡、韩国、中国台湾等亚太…...