住房城乡建设干部学院网站,织梦网站0day漏洞,网页打不开但是微信和qq都可以上,网站的静态资源服务器怎么做Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 前面大概讲了java进程问题分析流程#xff0c;这里再小结一下分析工具#xff0c;后面也会小结一下java进程问题分析定位。
1.分析工具 1.1.linux命令工具
参考#xff1a;Java web应用性能分析之【Linux服务器性…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、jpsJVM Process Status Tool现实指定系统内所有的HotSpot虚拟机进程 查看本机java进程信息jinfoConfiguration Info for Java虚拟机配置信息 查看jvm和系统参数信息。
2、jstackStack Track for java 显示虚拟机线程快照打印线程的栈信息制作 线程dump文件
3、jmap Memory map for java生成虚拟机的内存转储快照打印内存映射信息制作 堆dump文件
4、jstatJVM 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、jconsoleJConsole是一个基于JMX的GUI工具用于连接正在运行的JVM不过此JVM需要使用可管理的模式启动。简易的JVM可视化工具其功能被jvisualvm替代。
7、jvisualvm功能更强大的JVM可视化工具 jvisualVM所谓多合一虚拟机故障处理工具有强大的插件扩展功能通过安装插件扩展支持jvisualVM可以做到 a、显示虚拟机进程及进程的配置和环境信息jpsjinfo 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
简介 | arthashttps://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:jdwptransportdt_socket,servery,suspendn,address*:9999JDK 5-8-agentlib:jdwptransportdt_socket,servery,suspendn,address9999JDK 1.4.x-Xdebug -Xrunjdwp:transportdt_socket,servery,suspendn,address9999JDK 1.3.x or earlier-Xnoagent -Djava.compilerNONE -Xdebug-Xrunjdwp:transportdt_socket,servery,suspendn,address9999这里的9999则是服务端开放的端口后期客户端IDEA需要连接当前端口进行远程交互和调试。
但是我们需要注意的是这个9999端口在服务端一定要放开防火墙或者安全组
具体端口看项目需求运行服务端jar包程序则如下JDK 5-8版本java -jar -agentlib:jdwptransportdt_socket,servery,suspendn,address9999 ./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 请求信息跟踪
详细配置如下 !--用于检查系统的监控情况--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!--Spring Boot Admin Server监控服务端--dependencygroupIdde.codecentric/groupIdartifactIdspring-boot-admin-starter-server/artifactIdversion2.3.1/version/dependency!--增加安全防护防止别人随便进--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId/dependency启动类开启adminEnableAdminServer登录配置
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 LayoutOpenJDK提供的库用于查看Java对象的内存布局这个很有用可以借助它来跟踪锁升级等过程。只需要引入Maven即可使用。
//引入依赖dependencygroupIdorg.openjdk.jol/groupIdartifactIdjol-core/artifactIdversion0.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 获取 pidjstack -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-1Java 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 中每个线程对应一个十六进制的 nidnative 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 内部信息。
vmidJava 虚拟机进程 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 只输出活着的对象不指定则输出堆中所有对象
formatb 指定输出格式为二进制
file 指定文件名及文件存储位置例如jmap -dump:live,formatb,fileD:\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,formatb,filea.log pid
执行这个命令JVM 会将整个 heap 的信息 dump 到一个文件heap 如果比较大的话会导致这个过程比较耗时并且执行的过程中为了保证 dump 的信息是可靠的会暂停应用。
该命令通常用来分析内存泄漏 OOM通常做法是
首先配置 JVM 启动参数让 JVM 在遇到 OutOfMemoryError 时自动生成 Dump 文件
-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/path
使用命令 Dump Heap 信息
jmap -dump:formatb,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包含所有堆对象的状态二进制格式