使用JDK工具进行Java服务器应用程序故障排除
Java性能调优指南–有关提高Java代码性能的各种技巧。
最近又学到了很多新知识,感谢优锐课老师细致地讲解,这篇博客记录下自己所学所想。
1. 介绍
在Java世界中,我们大多数人习惯于在Java应用程序开发的所有阶段使用GUI工具:编写代码,对其进行调试和分析。我们通常更喜欢在开发环境中设置服务器环境,并尝试使用熟悉的工具在本地重现问题。不幸的是,由于各种原因,通常不可能在本地重现一些问题。例如,你可能无权访问服务器应用程序处理的真实客户端数据。
在这种情况下,你需要在服务器盒上远程对应用程序进行故障排除。你应该记住,你无法使用裸露的JRE来正确地对应用程序进行故障排除:它包含所有故障排除功能,但是实际上无法访问它。结果,你需要在同一盒子上使用JDK或某些第三方工具。本文将介绍JDK工具,因为与许多组织中需要安全审核的任何第三方工具相比,你可能被允许在生产环境中使用它。
通常,仅需将JDK发行包解压缩到你的包装盒中就足够了——你不需要出于故障排除的目的而正确安装它(实际上,在很多情况下不希望正确安装)。 对于基于JMX的功能,你实际上可以安装任何Java 7/8 JDK,但是某些工具无法识别将来的JDK,因此我建议你安装最新的Java 7/8 JDK或与服务器JRE完全匹配的内部版本-它允许 你会为当前没有访问安全点的应用程序转储应用程序堆(某些处于空闲模式的应用程序是“无安全点”应用程序的简单示例)。
2. 故障排除方案
2.1. 获取正在运行的JVM的列表
为了开始工作,你几乎总是需要获取正在运行的JVM,它们的进程ID和命令行参数的列表。 有时可能就足够了:你可能会发现同一应用程序的第二个实例同时执行相同的工作(并损坏输出文件/重新打开套接字/执行其他一些愚蠢的操作)。
只需运行jcmd而无需任何参数。 它将向你显示正在运行的JVM的列表:
3824 org.jetbrains.idea.maven.server.RemoteMavenServer
2196
780 sun.tools.jcmd.JCmd
现在,你可以通过运行jcmd <PID> help命令来查看哪些诊断命令可用于给定的JVM。 这是VisualVM的示例输出:
>jcmd 3036 help 3036:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help
键入jcmd <PID> <COMMAND_NAME>来运行诊断命令或得到一条错误消息,询问命令参数:
>jcmd 3036 GC.heap_dump 3036:
java.lang.IllegalArgumentException: The argument 'filename' is mandatory.
你可以使用以下命令获取有关诊断命令参数的更多信息:jcmd <PID>帮助<COMMANDNAME>。 例如,这是GC.heap_dump命令的输出:
>jcmd 3036 help GC.heap_dump 3036:
GC.heap_dump
Generate a HPROF format dump of the Java heap. Impact: High: Depends on Java heap size and content. Request a full GC unless the '-all' option is specified. Permission: java.lang.management.ManagementPermission(monitor) Syntax : GC.heap_dump [options] <filename> Arguments:
filename : Name of the dump file (STRING, no default value) Options: (options must be specified using the <key> or <key>=<value> syntax)
-all : [optional] Dump all objects, including unreachable objects (BOOLEAN, false)
2.2. 进行堆转储
jcmd为你提供了一个方便的界面,用于以HPROF格式进行堆转储。只需运行jcmd <PID> GC.heap_dump <FILENAME>。请注意,文件名是相对于正在运行的JVM当前目录而不是当前目录的,因此你可能需要指定完整路径。最好使用.hprof扩展名作为转储文件名。
线程转储完成后,你可以将文件复制到自己的盒子中,然后在VisualVM(它是JDK的一部分)中打开它,并使用其堆walker和查询语言功能,或将其加载到Java Mission Control的JOverflow插件中并对其进行分析各种内存问题。
注意1:当然,还有许多其他工具可以处理hprof文件:NetBeans,Eclipse Memory Analyzer,YourKit等。将.hprof文件下载到框中后,请使用你喜欢的工具。
注意2:你也可以使用jmap工具进行堆转储:jmap -dump:live,file = <FILE_NAME> <PID>。问题在于它被正式证明为不受支持。我们中的许多人都认为JDK中不受支持的内容将永远存在,但事实证明情况不再如此:JEP 240,JEP 241
2.3. 分析类直方图
如果你正在寻找内存泄漏,通常只对堆中某些特定类型的活动对象感兴趣。 例如,你可能知道一次只能拥有一个特定类型的对象(应用程序中的某种主要工作类)。 在旧的一代中可能还存在一个或多个相同类的实例,到目前为止,这些实例尚未进行垃圾回收,但是不应从应用程序根目录访问它们。
要打印类直方图,请运行以下两个命令之一(两个命令均打印活动对象的数量):
jcmd <PID> GC.class_histogram
jmap -histo:live <PID>
以下是示例输出的前几行:
num #instances #bytes class name
----------------------------------------------
1: 5923 5976952 [I
2: 50034 4127704 [C
3: 49465 1187160 java.lang.String
4: 188 1069496 [J
5: 3985 1067240 [Ljava.util.HashMap$Node;
6: 8756 982872 java.lang.Class
7: 2855 835792 [B
8: 23570 754240 java.util.HashMap$Node
9: 13964 671440 [Ljava.lang.Object;
10: 9642 308544 java.util.Hashtable$Entry
11: 4453 213744 java.util.HashMap
请注意,以字节为单位的已占用大小是一个较浅的大小–它不包含任何子对象。 很容易从char [](类名= [C]和String stats)中注意到这一事实–尽管实例数是相似的(尽管char []-s总是比String多,但是char []-的大小 s明显更大,如果String的大小包含基础char []的大小,则情况并非如此。
现在,你可以grep /搜索你感兴趣的类名称,并检查活动实例的数量。 如果看到的实例超出预期,请进行堆转储并在任何堆遍历器中对其进行分析(请参见上文)。
2.4. 进行线程转储
有时,你的应用程序可能会报告为“not doing anything/got stuck”。有很多种“stuck”的情况——死锁,高资源争用或仅是O(N10)算法来处理数百万用户的请求,在所有这些情况下,你应该知道你的应用程序线程正在执行什么以及锁将执行什么操作他们持有。
有两种类型的锁:基于同步关键字和Object.wait / notifyAll方法的原始锁,以及Java 5中引入的java.util.concurrent锁。它们之间的主要区别是前者绑定到你输入的堆栈框架上同步部分,并且在线程转储中始终可用。另一方面,后者(java.util.concurrent)不受堆栈框架限制——你可以使用一种方法输入锁,然后将其保留在另一种方法中。结果,一段时间以来,它们根本没有在线程转储中打印,即使现在它们仍然是一个选项。但是,你需要在线程转储中同时使用两种锁,以正确调查线程问题。
有3种打印应用程序线程转储的方法。你可以在Linux上运行kill -3 <PID>。 或者,你可以在任何平台上运行以下命令之一:
jstack <PID>
jcmd <PID> Thread.print
2.5. 运行Java Flight Recorder
到目前为止,本文中提到的所有工具仅应用于快速调查。 为了进行更深入的分析,我建议使用内置的Java Flight Recorder。
运行JFR是一个三步过程:
- 你需要创建一个包含所需设置的JFR模板文件。为此,请运行jmc并转到“窗口”->“飞行记录模板管理器”菜单。配置文件准备就绪后,将其导出到文件中,然后将其发送到你正在使用的框中。
- JFR需要JDK商业许可证。现在,你需要在所需的JVM上解锁商业功能:
jcmd <PID> VM.unlock_commercial_features
- 之后,你可以启动JFR。 这是命令行示例:
jcmd <PID> JFR.start name=test duration=60s settings=template.jfc filename=output.jfr
此命令立即运行JFR(未设置delay属性),并使用template.jfc模板文件中的设置并将结果写入output.jfr(在两个文件中都使用绝对路径),收集JVM信息60秒钟。
录制完成后,你可以将.jfr文件复制到笔记本电脑并在jmcGUI中对其进行分析。 它包含几乎所有你需要对JVM进行故障排除的信息,除了完整堆转储,你可以单独创建并复制到你的机器中。
感谢阅读!最后奉上近期整理出来的一套完整的java架构思维导图,分享给大家对照知识点参考学习。


使用JDK工具进行Java服务器应用程序故障排除的更多相关文章
- [置顶] JDK工具(一)–Java编译器javac
1.概述 javac.exe: Java编译器,将Java源代码转换成字节码. 2.用法 javac <选项> <源文件> (使用过程中发现,javac <源 ...
- JDK工具(一)–Java编译器javac
1.概述 javac.exe: Java编译器,将Java源代码转换成字节码. 2.用法 javac <选项> <源文件> (使用过程中发现,javac <源 ...
- 三、jdk工具之jstack(Java Stack Trace)
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
- 通过JDK常用工具监控Java进程的内存占用情况
目录 1 JDK 工具的使用 2 查看 GC 日志信息 3 添加 JMS 远程监控 Tomcat是一款常用的Web容器, 它是运行在 JVM(Java Virtual Machine) 中的一个Jav ...
- 八、jdk工具之JvisualVM、JvisualVM之二--Java程序性能分析工具Java VisualVM
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
- 十、jdk工具之Jdb命令(The Java Debugger)
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
- Windows 7下配置JDK环境变量,JAVA环境变量配置,Tomcat服务器的使用
参考来源: http://www.cnblogs.com/pannysp/archive/2012/03/07/2383364.html 1. 常识: 1.1 War包 War包一般是在进行Web开发 ...
- 使用linux perf工具生成java程序火焰图
pre.cjk { font-family: "Nimbus Mono L", monospace } p { margin-bottom: 0.1in; line-height: ...
- 五、jdk工具之jmap(java memory map)、 mat之四--结合mat对内存泄露的分析、jhat之二--结合jmap生成的dump结果在浏览器上展示
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
随机推荐
- [HNOI2008]GT考试(kmp,dp,矩阵乘法)
[HNOI2008]GT考试(luogu) Description 求有多少个n位的数字串不包含m位的字符串(范围 n <= 1e9 n<=1e9, m <= 20m<=20) ...
- HDU 3839 Ancient Messages(DFS)
In order to understand early civilizations, archaeologists often study texts written in ancient lang ...
- C语言博客作业7
本周作业头 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 作业链接 我在这个课程的目标是 熟练运用switch语句 这个作业在那个具体方面帮助我实现目标 完成pta作业 参考文献 文章 ...
- STM8 ADC1连续模式切换通道干扰问题的解决
初始化ADC1: void Init_ADC(void){ GPIO_Init(GPIOD, (GPIO_Pin_TypeDef)(GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|G ...
- I Love GPLT
这道超级简单的题目没有任何输入. 你只需要把这句很重要的话 —— “I Love GPLT”——竖着输出就可以了. 所谓“竖着输出”,是指每个字符占一行(包括空格),即每行只能有1个字符和回车. 输入 ...
- VC运行时库/MD、/MDd、/MT、/MTd说明
http://blog.csdn.net/holybin/article/details/26134153 VC运行时库设置:VC项目属性->配置属性->C/C++->代码生成-&g ...
- gRPC初识
RPC算是近些年比较火热的概念了,随着微服务架构的兴起,RPC的应用越来越广泛.本文介绍了RPC和gRPC的相关概念,并且通过详细的代码示例介绍了gRPC的基本使用. RPC是什么 在分布式计算,远程 ...
- 再次聚焦DOCKER MACHINE CODE 2048
如果有一种feeling让世界难以释怀,那一定是发掘(挖土机那家强?)了什么了不起的东西 如果有一种贴图叫做深夜,仍不止息,那一定是饱含深意的贴图 // TODO: I'm not super hap ...
- c语言小游戏-扫雷的完成
C语言-扫雷游戏 本文将对此游戏做一个大致的概述,此代码适合初学者,编写软件使用了vs2017. 该代码可以实现如下功能: 1.用户可以选择3个难度,分别布置不同个数的雷. 2.随机数设置雷的位置. ...
- Go语言实现:【剑指offer】左旋转字符串
该题目来源于牛客网<剑指offer>专题. 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左 ...