网站制作不用备案,网络平台的建设方案,网站制作费多少,做教育集团的网站建设面试题 你使用过Java虚拟机性能监控和故障处理工具吗#xff1f;#xff08;美图#xff09; 怎么打出线程栈信息。#xff08;字节跳动#xff09; JVM诊断调优工具用过哪些#xff1f; (京东) 怎么获取 Java 程序使用的内存#xff1f;堆使用… 面试题 你使用过Java虚拟机性能监控和故障处理工具吗美图 怎么打出线程栈信息。字节跳动 JVM诊断调优工具用过哪些 (京东) 怎么获取 Java 程序使用的内存堆使用的百分比国美 几种常用的内存调试工具你知道哪些搜狐 JVM诊断调优工具用过哪些 (蚂蚁金服) 概述 性能诊断是软件工程师在日常工作中需要经常面对和解决的问题在用户体验至上的今天解决好应用的性能问题能带来非常大的收益。 Java 作为最流行的编程语言之一其应用性能诊断一直受到业界广泛关注。可能造成 Java 应用出现性能问题的因素非常多例如线程控制、磁盘读写、数据库访问、网络I/O、垃圾收集等。想要定位这些问题一款优秀的性能诊断工具必不可少。 体会1使用数据说明问题使用知识分析问题使用工具处理问题。 体会2无监控、不调优
简单命令行工具 在我们刚接触java学习的时候大家肯定最先了解的两个命令就是javacjava那么除此之外还有没有其他的命令可以供我们使用呢我们进入到安装jdk的bin目录发现还有一系列辅助工具。这些辅助工具用来获取目标 JVM 不同方面、不同层次的信息帮助开发人员很好地解决Java应用程序的一些疑难杂症。
mac系统下 windows系统下 源码jdk/jdk11: 1ddf9a99e4ad /src/jdk.jcmd/share/classes/sun/tools/ jps查看正在运行的ava进程
jps(Java Process Status)显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息)可用于查询正在运行的虚拟机进程。
说明对于本地虚拟机进程来说进程的本地虚拟机ID与操作系统的进程ID是一致的是唯一的。
测试
public class JPSTest {public static void main(String[] args) {try {Thread.sleep(100000);} catch (InterruptedException e) {e.printStackTrace();}}
}
它的基本使用语法为 jps [options] [hostid] 我们还可以通过追加参数来打印额外的信息。
options参数 -q :仅仅显示LVMID (local virtual machine id)即本地虚拟机唯一id。不显示主类的名称等 -l: 输出应用程序主类的全类名 或 如果进程执行的是jar包则输出jar完整路径 -m: 输出虚拟机进程启动时传递给主类main()的参数 -v: 列出虚拟机进程启动时的JVM参数。 比如-Xms20m -Xmx50m是启动程序指定的jvm参数。 说明以上参数可以综合使用。 补充如果某 Java 进程关闭了默认开启的UsePerfData参数即使用参数-XX:-UsePerfData那么jps命令以及下面介绍的jstat将无法探知该 Java 进程。
hostid参数 RMI注册表中注册的主机名。如果想要远程监控主机上的 java 程序需要安装 jstatd。对于具有更严格的安全实践的网络场所而言可能使用一个自定义的策略文件来显示对特定的可信主机或网络的访问尽管这种技术容易受到IP地址欺诈攻击。如果安全问题无法使用一个定制的策略文件来处理那么最安全的操作是不运行jstatd服务器而是在本地使用jstat和jps工具。 jstat查看VM统计信息
jstat(JVM Statistics Monitoring Tool)用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
在没有GUI图形界面只提供了纯文本控制台环境的服务器上它将是运行期定位虚拟机性能问题的首选工具。常用于检测垃圾回收问题以及内存泄漏问题。
官方文档https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
它的基本使用语法为 jstat -option [-t] [-hlines] vmid [interval [count]] 查看命令相关参数jstat -h 或 jstat -help
option参数 选项option可以由以下值构成。 类装载相关的
-class显示ClassLoader的相关信息类的装载、卸载数量、总空间、类装载所消耗的时间等。 垃圾回收相关的
-gc显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。-gccapacity显示内容与-gc基本相同但输出主要关注Java堆各个区域使用到的最大、最小空间。-gcutil显示内容与-gc基本相同但输出主要关注已使用空间占总空间的百分比。-gccause与-gcutil功能一样但是会额外输出导致最后一次或当前正在发生的GC产生的原因。-gcnew显示新生代GC状况-gcnewcapacity显示内容与-gcnew基本相同输出主要关注使用到的最大、最小空间-geold显示老年代GC状况-gcoldcapacity显示内容与-gcold基本相同输出主要关注使用到的最大、最小空间-gcpermcapacity:显示永久代使用到的最大、最小空间。 JIT相关的
-compiler显示JIT编译器编译过的方法、耗时等信息-printcompilation输出已经被JIT编译的方法 -gc说明 1、新生代相关
S0C是第一个幸存者区的大小字节S1C是第二个幸存者区的大小字节S0U是第一个幸存者区已使用的大小字节S1U是第二个幸存者区已使用的大小字节EC是Eden空间的大小字节EU是Eden空间已使用大小字节
2、老年代相关
OC是老年代的大小字节OU是老年代已使用的大小字节
3、方法区元空间相关
MC是方法区的大小MU是方法区已使用的大小CCSC是压缩类空间的大小CCSU是压缩类空间已使用的大小
4、其它
YGC是指从应用程序启动到采样时young gc次数YGCT是指从应用程序启动到采样时young gc消耗的时间秒FGC是指从应用程序启动到采样时full gc次数FGCT是指从应用程序启动到采样时full gc消耗的时间秒GCT是指从应用程序启动到采样时gc的总时间
interval参数 用于指定输出统计数据的周期单位为毫秒。即查询间隔
count参数 用于指定查询的总次数
-t参数 可以在输出信息前加上一个Timestamp列显示程序的运行时间。单位秒 经验我们可以比较 Java 进程的启动时间以及总 GC 时间GCT 列或者两次测量的间隔时间以及总 GC 时间的增量来得出 GC 时间占运行时间的比例。如果该比例超过 20%则说明目前堆的压力较大如果该比例超过 90%则说明堆里几乎没有可用空间随时都可能抛出 OOM 异常。
-h参数 可以在周期性数据输出时输出多少行数据后输出一个表头信息
补充 jstat还可以用来判断是否出现内存泄漏。 第1步在长时间运行的 Java 程序中我们可以运行jstat命令连续获取多行性能数据并取这几行数据中 OU 列即已占用的老年代内存的最小值。 第2步然后我们每隔一段较长的时间重复一次上述操作来获得多组 OU 最小值。如果这些值呈上涨趋势则说明该 Java 程序的老年代内存已使用量在不断上涨这意味着无法回收的对象在不断增加因此很有可能存在内存泄漏。 jinfo实时查看和修改VM配置参数
jinfo(Configuration Info for Java)查看虚拟机配置参数信息也可用于调整虚拟机的配置参数。
在很多情况下Java应用程序不会指定所有的Java虚拟机参数。而此时开发人员可能不知道某一个具体的Java虚拟机参数的默认值。在这种情况下可能需要通过查找文档获取某个参数的默认值。这个査找过程可能是非常艰难的。但有了jinfo工具开发人员可以很方便地找到Java虚拟机参数的当前值。 官方帮助文档jinfo
它的基本使用语法为 jinfo [ options ] pid 说明java 进程ID 必须要加上 查看示例 示例1jinfo -sysprops PID 可以查看由System.getProperties0取得的参数 示例2jinfo -flags PID 查看曾经赋过值的一些参数 示例3jinfo -flag 具体参数 PID 查看某个java进程的具体参数的值
修改示例 jinfo不仅可以查看运行时某一个Java虚拟机参数的实际取值甚至可以在运行时修改部分参数并使之立即生效。但是并非所有参数都支持动态修改。参数只有被标记为manageable的flag可以被实时修改。其实这个修改能力是极其有限的。 # 可以查看被标记为manageable的参数 java -XX:PrintFlagsFinal -version | grep manageable
intx CMSAbortablePrecleanWaitMillis 100 {manageable} intx CMSWaitDuration 2000 {manageable} bool HeapDumpAfterFullGC false {manageable} bool HeapDumpBeforeFullGC false {manageable} bool HeapDumpOnOutOfMemoryError false {manageable} ccstr HeapDumpPath {manageable} uintx MaxHeapFreeRatio 100 {manageable} uintx MinHeapFreeRatio 0 {manageable} bool PrintClassHistogram false {manageable} bool PrintClassHistogramAfterFullGC false {manageable} bool PrintClassHistogramBeforeFullGC false {manageable} bool PrintConcurrentLocks false {manageable} bool PrintGC false {manageable} bool PrintGCDateStamps false {manageable} bool PrintGCDetails false {manageable} bool PrintGCTimeStamps false {manageable} 针对boolean类型jinfo -flag [|-]具体参数 PID 针对非boolean类型jinfo -flag 具体参数具体参数值 PlD
拓展 java -XX:PrintFlagsInitial 查看所有VM参数启动的初始值 java -XX:PrintFlagsFinal 查看所有VM参数的最终值 java -XX:PrintCommandLineFlags 查看那些已经被用户或者JVM设置过的详细的XX参数的名称和值 jmap导出内存映像文件内存使用情况
jmap(JVM Memory Map)作用一方面是获取dump文件堆转储快照文件二进制文件它还可以获取目标Java进程的内存相关信息包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。
开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。
官方帮助文档jmap
它的基本使用语法为 jmap [option] pid jmap [option] executable core jmap [option] [server_id]remote server IP or hostname 其中option包括 说明这些参数和linux下输入显示的命令多少会有不同包括也受jdk版本的影响。
-dump 生成Java堆转储快照dump文件特别的-dump:live只保存堆中的存活对象
-heap 输出整个堆空间的详细信息包括GC的使用、堆配置信息以及内存的使用信息等
-histo 输出堆中对象的统计信息包括类、实例数量和合计容量特别的-histo:live只统计堆中的存活对象
-permstat 以ClassLoader为统计口径输出永久代的内存状态信息仅linux/solaris平台有效
-finalizerinfo 显示在F-Queue中等待Finalizer线程执行finalize方法的对象仅linux/solaris平台有效
-F 当虚拟机进程对-dump选项没有任何响应时可使用此选项强制执行生成dump文件仅linux/solaris平台有效
-h | -help jmap工具使用的帮助命令
-J flag 传递参数给jmap启动的jvm
基本使用 使用1导出内存映像文件 一般来说使用jmap指令生成dump文件的操作算得上是最常用的jmap命令之一,将堆中所有存活对象导出至一个文件之中。 Heap Dump又叫做堆存储文件指一个Java进程在某个时间点的内存快照。Heap Dump在触发内存快照的时候会保存此刻的信息如下
All ObjectsClass,fields,primitive values and referencesAll ClassesClassLoader,name,super class,static fieldsGarbage Collection RootsObjects defined to be reachable by the JVMThread Stacks and Local VariablesThe call-stacks of threads at the moment of the snapshot,and per-frame information about local objects 说明1. 通常在写Heap Dump文件前会触发一次Full GC所以heap dump文件里保存的都是FullGC后留下的对象信息。2. 由于生成dump文件比较耗时因此大家需要耐心等待尤其是大内存镜像生成dump文件则需要耗费更长的时间来完成。 手动的方式 jmap -dump:formatb,filefilename.hprof pid jmap -dump:live,formatb,filefilename.hprof pid 自动的方式当程序发生OOM退出系统时一些瞬时信息都随着程序的终止而消失而重现OOM问题往往比较困难或者耗时。此时若能在OOM时自动导出dump文件就显得非常迫切。 -XX:HeapDumpOnOutOfMemoryError在程序发生OOM时导出应用程序的当前堆快照。 -XX:HeapDumpPathfilename.hprof可以指定堆快照的保存位置。 示例-Xmx100m -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPathD:\m.hprof 使用2显示堆内存相关信息 jmap -heap pid -jmap -histo pid 使用3其它作用 jmap -permstat pid查看系统的ClassLoadert信息 jmap -finalizerinfo查看堆积在finalizer队列中的对象
小结 由于jmap将访问堆中的所有对象为了保证在此过程中不被应用线程干扰jmap需要借助安全点机制让所有线程停留在不改变堆中数据的状态。也就是说由jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。 举个例子假设在编译生成的机器码中某些对象的生命周期在两个安全点之间那么:live选项将无法探知到这些对象。 另外如果某个线程长时间无法跑到安全点jmap将一直等下去。 与前面讲的jstat则不同垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中而jstat只需直接读取即可。 jhatJDK自带堆分析工具
jhat(JVM Heap Analysis Tool)Sun JDK提供的jhat命令与jmap命令搭配使用用于分析jmap生成的heap dump文件堆转储快照。jhat内置了一个微型的HTTP/HTML服务器 生成dump文件的分析结果后 用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。
使用了jhat命令就启动了一个http服务端口是7000即http://localhost:7000/就可以在浏览器里分析。
说明jhat命令在JDK9、JDK10中已经被删除官方建议用VisualVM代替。
它的基本使用语法为 jhat [option] [dumpfile] option参数-stack false|true 关闭 | 打开对象分配调用栈跟踪
option参数-refs false|true 关闭 | 打开对象引用跟踪
option参数-port port-number 设置jhat HTTP Server的端口号默认7000
option参数-exclude exclude-file 执行对象查询时需要排除的数据成员列表文件
option参数-baseline exclude-file 指定一个基准堆转储
option参数-debug int 设置debug级别
option参数-version 启动后显示版本信息就退出
option参数-J flag 传入启动参数比如 -J -Xmx512m jstack打印VM中线程快照 面试题 JVM的进程有哪些线程启动有了解吗神州租车 面试题解释 每当使用java命令执行一个带main方法的类时就会启动JVM应用程序实际上就是在操作系统中启动一个JVM进程JVM启动时必然会创建以下5个线程 1-main 主线程执行我们指定的启动类的main方法 2-Reference Handler 处理引用的线程 3-Finalizer 调用对象的finalize方法的线程就是垃圾回收的线程 4-Signal Dispatcher 分发处理发送给JVM信号的线程 5-Attach Listener 负责接收外部的命令的线程 Attach Listener 该线程是负责接收到外部的命令执行该命令并且把结果返回给发送者。通常我们会用一些命令去要求jvm给我们一些反馈信息如java -version、jmap、jstack等等。如果该线程在jvm启动的时候没有初始化那么则会在用户第一次执行jvm命令时得到启动。 signal dispather 前面我们提到第一个Attach Listener线程的职责是接收外部jvm命令当命令接收成功后会交给signal dispather线程去进行分发到各个不同的模块处理命令并且返回处理结果。signal dispather线程也是在第一次接收外部jvm命令时进行初始化工作。 FinalizerJVM在垃圾收集时会将失去引用的对象包装成Finalizer对象Reference的实现并放入ReferenceQueue由Finalizer线程来处理最后将该Finalizer对象的引用置为null由垃圾收集器来回收。 Reference Handler 它主要用于处理引用对象本身软引用、弱引用、虚引用的垃圾回收问题。 main主线程用于执行我们编写的java程序的main方法。 编写java应用程序查看JVM启动时创建的所有线程代码如下
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;public class JVMTest {public static void main(String[] args) throws Exception {ThreadMXBean threadMXBean ManagementFactory.getThreadMXBean();ThreadInfo[] threadInfos threadMXBean.dumpAllThreads(false, false);for(ThreadInfo threadInfo : threadInfos) {System.out.println(threadInfo.getThreadId() - threadInfo.getThreadName());}}
}
//输出如下
//5-Attach Listener
//4-Signal Dispatcher
//3-Finalizer
//2-Reference Handler
//1-main
jstack(JVM Stack Trace)用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。 线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。
生成线程快照的作用可用于定位线程出现长时间停顿的原因如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时就可以用jstack显示各个线程调用的堆栈情况。
官方帮助文档jstack
在thread dump中要留意下面几种状态
死锁Deadlock重点关注 等待资源Waiting on condition重点关注 等待获取监视器Waiting on monitor entry重点关注 阻塞Blocked重点关注 执行中Runnable暂停Suspended对象等待中Object.wait() 或 TIMED_WAITING 停止Parked
它的基本使用语法为 jstack option pid jstack管理远程进程的话需要在远程程序的启动参数中增加
-Djava.rmi.server.hostname…..-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port8888-Dcom.sun.management.jmxremote.authenticatefalse-Dcom.sun.management.jmxremote.sslfalse
option参数-F 当正常输出的请球不被响应时强制输出线程堆栈
option参数-l 除堆栈外显示关于锁的附加信息
option参数-m 如果调用到本地方法的话可以显示C/C的堆栈
option参数-h 帮助操作 jcmd多功能命令行
在JDK 1.7以后新增了一个命令行工具jcmd。它是一个多功能的工具可以用来实现前面除了jstat之外所有命令的功能。比如用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。
官方帮助文档jcmd
jcmd拥有jmap的大部分功能并且在Oracle的官方网站上也推荐使用jcmd命令代jmap命令。
基本使用语法
jcmd -I 列出所有的VM进程
jcmd pid help 针对指定的进程列出支持的所有命令
jcmd pid 具体命令 显示指定进程的指令命令的数据 你可以探索jcmd中的下述功能看看有没有适合你项目的监控项
Compiler.CodeHeap_AnalyticsCompiler.codecacheCompiler.codelistCompiler.directives_addCompiler.directives_clearCompiler.directives_printCompiler.directives_removeCompiler.queueGC.class_histogramGC.class_statsGC.finalizer_infoGC.heap_dumpGC.heap_infoGC.runGC.run_finalizationVM.class_hierarchyVM.classloader_statsVM.classloadersVM.command_lineVM.dynlibsVM.flagsVM.infoVM.logVM.metaspaceVM.native_memoryVM.print_touched_methodsVM.set_flagVM.stringtableVM.symboltableVM.system_propertiesVM.systemdictionaryVM.unlock_commercial_featuresVM.uptimeVM.version jstatd远程主机信息收集
之前的指令只涉及到监控本机的Java应用程序而在这些工具中一些监控工具也支持对远程计算机的监控如jps、jstat。为了启用远程监控则需要配合使用jstatd 工具。
命令jstatd是一个RMI服务端程序它的作用相当于代理服务器建立本地计算机与远程监控工具的通信。 jstatd服务器将本机的Java应用程序信息传递到远程计算机。