“我们喜欢关注Mikhail Vorontsov的博客,并获得他对Java Performance相关问题的看法。 我们曾多次被问到Takipi的Java错误分析与Java Mission Control和Java Flight Recorder有何不同。 因此,尽管工具之间的差异很大(主要是,JMC主要是桌面应用程序,而Takipi是专门为大型生产环境设计的),但我们认为这是增加JMC全面概述的好机会。
除了Java Mission Control是桌面应用程序之外,主要的区别在于使用Takipi,您将获得始终在线的错误分析,直到导致每次错误的变量值和实际代码。 因此,在JMC在概要分析中具有很高的价值,但在堆栈跟踪级别停止的情况下,Takipi会深入研究实际代码以帮助您重现和解决生产错误。
另一个区别是使用分布式系统,JMC可在单台计算机上工作,而Takipi的仪表板可在不同的计算机上显示多个JVM。 因此,如果您要监视大型生产系统,请尝试Takipi。 但是,如果您正在寻找一款出色的桌面分析工具,那么JMC可能就是您的最佳选择。”
–塔基皮(Takipi)Alex Zhitnitsky
新帖:Oracle Java任务控制:终极指南http://t.co/UaxThmzq61 pic.twitter.com/i0UScStu9u
— Takipi(@takipid) 2015年3月23日
Mikhail是java-performance.info的首席博客作者。 他一遍又一遍地工作,使Java应用程序速度提高了5%,而且更加紧凑。 Mikhail喜欢在悉尼(澳大利亚)的一个郊区度过园艺和陪伴儿子的时光。
目录
1. 简介
2. Java任务控制
3. JMC许可证 4. 实时过程监控 – 4.1 事件触发 – 4.2 内存选项卡 – 4.3 线程选项卡 5. 使用Java Flight Recorder – 5.1 如何运行 – 5.2 初始屏幕 – 5.3 内存选项卡 – 5.4 分配选项卡 – – 5.4.1 按类别 – – 5.4.2 通过线程 – – 5.4.3 分配配置文件 – 5.5 代码选项卡 – – 5.5.1 热门方法 – – 5.5.2 例外选项卡 – – 5.5.3 线程选项卡 – – 5.5.4 I / O选项卡 6. Java生产工具生态系统
1.简介
本文将介绍Java Mission Control(一种自Java 7u40起可用的JDK GUI工具)以及Java Flight Recorder。
2. Java任务控制
从Java 7u40开始, Oracle Java Mission Control是Oracle JDK中提供的工具。 该工具源自JRockit JVM,已有多年的历史。 由两名JRockit高级开发人员撰写的Oracle JRockit:权威指南中对JRockit及其版本的JMC进行了很好的描述(另请访问Marcus Hirt博客 –您应该查找JMC任何新闻的第一位)。
Oracle JMC可以用于两个主要目的:
- 监视多个正在运行的Oracle JVM的状态
- Java Flight Recorder转储文件分析
3. JMC许可证
当前的JMC许可证(请参见此处的 “补充许可条款”)允许您自由使用JMC进行开发,但是如果要在生产中使用它,则需要购买商业许可证。
4.实时过程监控
您可以通过在主窗口的“ JVM浏览器”选项卡中右键单击并选择“启动JMX控制台”菜单选项来附加到JVM。 您将看到以下屏幕。 这里没有什么花哨的地方,只需注意“ +”按钮,您可以在该屏幕上添加更多的计数器。
4.1事件触发
触发器允许您运行各种操作,以响应某些JMX计数器超过给定时间段(可选)并保持在阈值以上。 例如,您可以在足够长时间的高CPU活动的情况下触发JFR记录,以了解是什么原因导致的(并且您不仅限于单个记录!)。
请注意,触发器可以在任何JMX计数器上运行(您是否看到“添加...”按钮?)–您可以设置比标准分发版中可用触发器更多的触发器,并将设置导出到磁盘上。 您甚至可以使用自己的应用程序JMX计数器。
转到“规则详细信息”窗口中的“操作”选项卡–您可以在此处指定在发生事件时要执行的操作。
请注意,如果要正确使用JFR,您需要至少在Java 7 update 40中运行您的应用程序–我无法记录Java7u40之前的JRE的任何事件(可能是某些JRE版本之间的错误或不兼容……) 。
4.2内存选项卡
下一个选项卡–“内存”将为您提供有关应用程序堆和垃圾回收的摘要信息。 请注意,您可以运行完整的GC并从该页面请求堆转储(在屏幕截图中突出显示)。 但从本质上讲,此页面只是一个不错的UI,围绕着其他来源提供的功能。
4.3线程选项卡
此标签可让您查看应用程序中正在运行的线程及其当前堆栈转储的列表(每秒更新一次)。 它还可以让您看到:
- 线程状态-运行或阻塞/等待
- 锁名
- 如果线程死锁
- 线程被阻止的次数
- 每线程CPU使用率!
- 自启动以来,给定线程分配的内存量
请记住,您必须打开CPU分析,死锁检测和内存分配跟踪才能以实时模式获取该信息:
5.使用Java Flight Recorder
Java Flight Recorder(在本文的其余部分中将其称为JFR)是JMC的功能。 从用户的角度来看,您以固定的记录时间/最大记录文件大小/最大记录长度(您的应用可以在此之前完成)运行JFR,然后等待直到记录完成。 之后,您可以在JMC中对其进行分析。
5.1如何运行JFR
您需要向要连接的JVM添加以下两个选项:
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
接下来,如果您想从JFR获得任何有用的信息,则需要连接到Java 7u40或更高版本。 文档声称您可以从Java 7u4连接到任何JVM,但是我无法从这些JVM中获得任何有用的信息。
要记住的第三件事是,默认情况下,JVM仅允许在安全点进行堆栈跟踪。 因此,在某些情况下,您可能有不正确的堆栈跟踪信息。 如果要更精确的堆栈跟踪, JFR文档会告诉您设置另外两个参数(您将无法在运行的JVM上设置这些参数):
-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints
最后,如果您希望有尽可能多的文件I / O,Java异常和CPU性能分析信息,请确保已选择启用参数,并将其阈值设置为“ 1 ms”。
5.2 JFR初始屏幕
JFR记录的初始屏幕包含记录期间的CPU和堆使用情况图表。 将其视为您的过程的概述。 在此(和其他JFR屏幕)上,您唯一需要注意的是可以通过任何图表选择时间范围进行分析的功能。 勾选“同步选择”复选框,以在每个窗口上保持相同的时间范围–这将使您仅检查在此范围内发生的事件。
此屏幕上还有一个有趣的功能:底部的“ JVM信息”选项卡包含在已配置的JVM中设置的所有JVM参数的值。 您可以通过-XX:+ PrintFlagsFinal JVM选项获取它们,但是通过UI远程获取它们更为方便:
5.3 Java Flight Recorder的“内存”选项卡
内存选项卡为您提供有关以下信息:
- 机器RAM和Java堆的使用情况(您可以轻松地猜测在录制过程中是否发生了交换或GC过多)。
- 垃圾收集–何时,为什么,清理多长时间和清理多少空间。
- 内存分配–在TLAB内部/外部,按类/线程/堆栈跟踪。
- 堆快照–类名占用的内存数量/数量
本质上,此选项卡将使您可以检查应用程序中的内存分配率,它对GC施加的压力以及哪些代码路径导致了意外的高分配率。 JFR还具有其非常特殊的功能–它允许分别跟踪TLAB和全局堆分配(TLAB分配要快得多,因为它们不需要任何同步)。
通常,如果满足以下条件,您的应用将变得更快:
- 它分配较少的对象(按分配的RAM数量和数量)
- 您的旧(完整)垃圾收集较少,因为它们速度较慢并且需要停止运行(至少一段时间)
- 您已将非TLAB对象分配最小化
让我们看看如何监视此信息。 “概述”选项卡显示有关内存消耗/分配/垃圾收集的常规信息。
您可以在此处查看“预留堆”与“预留堆”的距离。 它显示了在输入尖峰的情况下您有多少保证金。 蓝线(“ Used Heap”)显示了旧一代中有多少数据正在泄漏/保持:如果您的锯切模式随着每一步的增长而增加,则旧一代正在增长。 每个步骤的最低点大约显示了旧一代中的数据量(其中某些数据可能符合垃圾收集的条件)。 屏幕截图上的模式表明,应用程序仅分配由年轻一代GC收集的短寿命对象(可能是一些无状态的处理)。
您还可以检查“ TLAB的分配率”字段-它显示每秒分配多少内存(还有另一个计数器称为“对象的分配率”,但通常应该很低)。 126 Mb / sec(在示例中)是批处理的相当平均速率(将其与HDD读取速度进行比较),但对于大多数交互式应用程序而言却很高。 您可以将此数字用作总体对象分配优化的指标。
以下三个选项卡:“垃圾回收”,“ GC时间”和“ GC配置”非常明显,它们可能是有关GC原因和GC导致的最长暂停(这会影响您的应用程序延迟)的信息来源。
5.4 Java Flight Recorder的“分配”选项卡
“分配”选项卡为您提供有关所有对象分配的信息。 您应该转到“在新的TLAB中分配”标签。 在这里,您可以看到每个类(正在分配哪些类实例),每个线程(哪个线程分配了大多数对象)或每个调用堆栈(将其作为全局分配信息进行处理)的对象分配配置文件。
5.4.1按类别分配
让我们看看您可以从每个选项卡中找到什么。 第一个(在上面的屏幕快照中)“按类分配”使您可以查看分配了最多类的类。 在中间选项卡中选择一种类型,您将获得该类实例的所有分配的分配统计信息(带有堆栈跟踪)。
您应该在这里进行的第一步检查是,是否找到任何“无用的”对象分配:任何原始包装器,例如Integer或Double(通常指示使用JDK集合), java.util.Date , java.util.GregorianCalendar , Pattern ,任何格式化程序等。我在最近的文章的第二部分中写了一些内存调整提示。 “堆栈跟踪”选项卡将使您找到需要改进的代码。
要检查的另一个问题是过多的对象分配。 不幸的是,这里没有给出一般性建议-您应该使用常识来理解“过多”在应用程序中的含义。 常见的问题是无用的防御性复制(对于只读客户端)和String.substring的过度使用,因为Java 7u6中 String类发生了更改。
5.4.2通过线程分配
如果您的应用程序中有几种数据处理类型的线程(或者您可以区分哪些任务由哪个线程运行),“按线程分配”选项卡可能会很有趣–在这种情况下,您可以找出每个线程的对象分配:
5.4.3分配配置文件
如果所有线程都是统一的(或者您只有一个数据处理线程),或者您只想查看高级分配信息,则直接转到“分配配置文件”选项卡。 在这里,您将看到在所有线程中的每个调用堆栈上分配了多少内存。
此视图使您可以找到对内存子系统施加最大压力的代码路径。 您应在此处区分预期分配和过度分配。 例如,如果从方法A多次调用方法B,并且方法B在其中分配了一些内存,并且保证方法B的所有调用都返回相同的结果–这意味着您过多地调用了方法B。过多的方法调用的另一个示例/ object分配可以是Logger.log调用中的字符串连接 。 最后,提防任何迫使您创建可重复使用对象的优化–仅在每个线程存储的对象不超过一个的情况下才应池/缓存对象(众所周知的示例是ThreadLocal <DateFormat> )。
5.5 Java Flight Recorder的“代码”选项卡
JFR视图中的下一个大标签是“代码”标签。 这对于CPU优化非常有用:
概述选项卡为您提供2个视图:“热程序包”和“热类”,在这里您可以查看每个Java包所花费的时间,在“热类”中,您可以查看应用程序中CPU最昂贵的类。
如果您使用一些对它们几乎没有控制权的第三方库,并且希望获得代码(一个软件包),第三方代码(其他一些软件包)和JDK(一个几个软件包)。 同时,我将其称为“ CIO / CTO视图”,因为它不是交互式的,并且不能让您看到这些包中的哪些类应归咎于。 作为开发人员,最好在此标签中的大多数其他表上使用过滤:
5.5.1热门方法/调用树选项卡
实际上,“ Hot Methods”和“ Call Tree”选项卡是任何Java分析器提供的普通视图。 它们显示了您的应用程序热点-应用程序花费了大部分时间的方法以及导致这些热点的代码路径。 通常,您应该从“热方法”选项卡开始调整应用程序CPU,然后在“调用树”选项卡中检查整体图像是否足够合理。
您应该意识到,所有“低影响”分析器都在使用采样来获取CPU概要文件。 采样探查器会定期对所有应用程序线程进行堆栈跟踪转储。 通常的采样时间为10毫秒。 通常不建议将此时间缩短到少于1 ms,因为采样影响将开始变得明显。
结果,您将看到的CPU配置文件在统计上是有效的,但并不精确。 例如,您可能不太幸运在采样间隔内碰到一些很少见的方法。 有时会发生这种情况……如果您怀疑探查器向您显示的信息不正确,请尝试重新组织“热”方法–将方法内联到最热路径的调用方中,或者相反,尝试将方法拆分为2部分–足以从探查器视图中删除方法。
5.5.2例外选项卡
“例外”选项卡是“代码”视图中的最后一个选项卡,在常规优化情况下值得关注。 引发Java异常非常慢 ,必须严格限制它们在高性能代码中的特殊使用情况。
“例外”视图将为您提供有关记录过程中引发的例外数量及其堆栈跟踪和详细信息的统计信息。 浏览“概述”标签,然后查看是否看到:
- 任何意外的例外
- 意外的异常数量
如果发现任何可疑的内容,请转到“例外”选项卡并检查例外的详细信息。 尝试摆脱至少大多数。
5.6 JFR线程选项卡
“ JFR线程”选项卡为您提供以下信息:
- CPU使用率/线程计数表
- 每个线程的CPU配置文件–与“代码”选项卡上的配置文件类似,但基于每个线程
- 竞争–哪些线程被哪些线程阻塞以及持续多长时间
- 延迟–导致应用程序线程进入等待状态的原因(您将在此处清楚地看到一些JFR开销)
- 锁实例–导致线程争用的锁
我不会在本文中详细介绍此选项卡,因为仅对于高级高级优化(例如锁剥离,原子/易失变量,非阻塞算法等)才需要此选项卡。
5.7 JFR I / O选项卡
“ I / O”选项卡应用于检查应用程序中的文件和套接字输入/输出。 它使您可以查看应用程序正在处理的文件,读/写的大小以及完成I / O操作所需的时间。 您还可以在应用程序中查看I / O事件的顺序。
与大多数其他Java Flight Recorder选项卡一样,您需要自己解释此选项卡的输出。 以下是一些您可能会问自己的示例问题:
- 我是否看到任何意外的I / O操作(在我不希望在此处看到的文件上)?
- 我是否多次打开/读取/关闭同一文件?
- 是否需要读/写块大小? 他们不是太小了吗?
请注意,如果使用SSD,强烈建议将“文件读取阈值” JFR参数(可以在开始JFR记录时进行设置)减小到1 ms。 您可能会错过默认值为10毫秒阈值的SSD上太多的I / O事件。 I / O“概述”选项卡很棒,但与以下4个专用选项卡相比,它不提供任何额外的信息。 4个专用选项卡(文件读/写,套接字读/写)中的每个选项卡彼此相似,因此让我们看一下其中的一个-“文件读”。
这里有3个标签:“按文件”,“按线程”和“按事件”。 前两个选项卡按文件和线程将操作分组。 最后一个选项卡仅列出所有I / O事件,但是如果您要调查对特定文件执行了哪些操作(按“路径”过滤),或者想弄清楚是否短时发出了读取请求,则该选项卡可能非常有用。大量数据(按“读取的字节数”排序),这会损害应用程序的性能。 通常,您应该始终缓冲磁盘读取,以便仅文件尾部读取会小于缓冲区大小。
请注意,I / O信息也是通过采样收集的,因此“ I / O”选项卡中将缺少某些(或很多)文件操作。 这在顶级固态硬盘上尤其明显。
还有一个相关的屏幕,使您可以按各个字段对I / O(和其他一些)事件进行分组。 例如,您可能想要找出多少个读操作已读取给定数量的字节(并检查其堆栈跟踪)。 转到JFR视图左侧的“事件”标签,然后转到最后一个名为“直方图”的标签。
您可以在此处按可用列对各种事件进行过滤/排序/分组。 每个JFR事件都有一个相关的堆栈跟踪,因此您可以查看所选事件的堆栈跟踪信息:
JFR没有涵盖一个基本的性能调优领域:内存使用反模式,例如重复的字符串或容量很大的几乎为空的集合。 JFR不为您提供此类信息,因为您需要进行堆转储才能进行此类分析。 那是您需要一个名为“ JOverflow Analysis”的JMC插件的地方。
6. Java生产工具生态系统
在Takipi的先前文章中,我们介绍了用于生产的Java工具生态系统。 如果您想发现更多新工具,可以查看以下文章:
- 主要版本发布后Java开发人员应使用的15种工具
- 异步进入主流:您必须知道的7种反应式编程工具
- Java开发人员应该知道的7种新工具
翻译自: https://www.javacodegeeks.com/2015/03/oracle-java-mission-control-the-ultimate-guide.html