HotSpot VM的设计者们认为为它的使用者和开发者提供充分的信息来诊断和修复VM的致命错误是重要的。一个常见大的VM致命错误是OutOfMemoryError。另一个在Solaris和Linux平台常见的致命错误是分段错误。也就是Windows上所说的访问冲突错误。当这些致命的错误发生时,理解根本原因然后去修复它就是非常重要的。有时根本问题的解决会引起Java应用的改变,有时根本错误就在HotSpot VM里。当HotSpot遇到一个致命错误时,它生成一个HotSpot错误日志文件,这个文件被命名为hs_err_pid<pid>.log,这里的<pid>被HotSpot出错时的进程id替换。hs_err_pid<pid>.log文件被创建在HotSpot VM被启动的目录。由于这个特性最初在HotSpot VM1.4.2版本开始被介绍,许多增强的信息被创建来诊断致命错误造成的根本原因。这些增强的信息包括:
- 一个内存map被包含进了hs_err_pid<pid>.log这个错误日志文件从而更容易的看到当VM出错时内存是如何泄露的
- 提供了--XX:ErrorFile命令行选项,能够设置hs_err_pid<pid>.log错误日志文件的路径。
- OutOfMemoryError也可以引起hs_err_pid<pid>.log文件的生成。
另一个比较流行来诊断VM致命错误根本原因的方式是使用HotSpot VM命令行选项 --XX:OnError=cmd1 args...;com2...这个命令行选项执行--OnError给定的命令列表无论HotSpot在什么时候崩溃。这个特性常用于调用一个调试器比如Linux/Solaris dbx或者是Windows Winddbg来立即检查崩溃。对于那些已发布的不支持-XX:OnError的版本,另一个HotSpot VM,命令行选项-XX:+ShowMessageBoxOnError可以被使用。这个选项在VM退出前通过弹出一个对话框提示HotSpot VM出现了一个致命错误来终止VM。这提供了一个时机来将HotSpot VM优先于退出依附于一个调试器。
当HotSpot VM遇到一个致命错误,内部会用一个叫做VMError的类来记录和生成hs_err_pid<pid>.log文件。当一个可识别的信号或者异常被检测到时,VMError类就被特定的指令调用。
提示:HotSpot VM使用信号来进行内部交流。当一个信号没被接收HotSpot VM的致命错误处理程序将被调用。这中没有被接收的情况可能来自于应用JNI code的错误,操作系统本地库,jre本地库或者HotSpot VM本身。
当关键的锁比如内存分配锁被持有时,HotSpot VM的致命错误处理程序必须小心的来写以避免自身成为引起错误的原因,比如StackOverflow或者致命错误。
由于OutOfMemoryError很可能遇到,尤其是在一些大规模的应用上,为用户提供有用的诊断信息从而使问题很快被确定就变得很重要。很常见的一种做法是简单的开大Java heap的大小。当OutOfMemoryError发生时,错误信息指示了哪种类型的内存是有问题的。例如:有可能是Java堆空间或者是永久代空间被指定的太小了。从java6开始,HotSpot VM产生的错误信息中包含了栈路径。当OutOfMemoryError第一次被抛出的时候,-XX:OutOfMemoryError=<cmd>选项的使用可以是命令被执行。值得一提的一个附加的有用特性是可以存储关于OutOfMemoryError的堆信息。通过指定-XX:+HeapDumpOnOutOfMemeoryError这个HotSpot VM命令行选项可以使这个特性生效。还有另外一个命令行选项-XX:HeapDumpPath=<pathname>允许用户定义堆信息将被存储在哪里的路径。
尽管应用程序的编写意图在避免线程死锁,但是开发者有时会犯错然后就导致死锁。当死锁发生了,在WIndows上按Ctrl+Break可以强制一个Java层级的线程栈打印标准的输出。在Solaris和Linux上,发送一个SIGQUIT信号给Java进程id完成同样的操作。分析一个线程轨迹可以分析死锁的源头。从Java6开始,绑定的JConsole工具增加了依附于Java进程来分析死锁的根本原因的功能。大多数情况下,死锁是由于错误的获取锁的顺序引起的。