<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; JMC</title>
	<atom:link href="https://blog.gmem.cc/tag/jmc/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Mon, 06 Apr 2026 12:46:48 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>使用Oracle Java Mission Control监控JVM运行状态</title>
		<link>https://blog.gmem.cc/jvm-monitoring-with-oracle-jmc</link>
		<comments>https://blog.gmem.cc/jvm-monitoring-with-oracle-jmc#comments</comments>
		<pubDate>Thu, 06 Nov 2014 03:11:25 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JMC]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[性能剖析]]></category>

		<guid isPermaLink="false">http://blog.gmem.cc/?p=2525</guid>
		<description><![CDATA[<p>简介 Oracle  Java Mission Control（以下称JMC）是一个集成到JVM（jdk7u40+）的性能剖析和诊断工具，相比起JProfiler之类的性能剖析工具，JMC更加简单易用，界面友好。 JMC使用了JVM内部特定的基于事件的接口，不同于一般性能剖析工具使用JVMPI/JVMTI方式实现。因此JMC几乎不会给应用造成额外的压力，可以用在负载很高的生产环境中： JFR在默认设置continuous下运行几乎对性能没有影响 JFR在默认设置profiling下运行通常造成小于2%的性能下降 在JDK 7 Update 40及其以后的版本中已经集成了JMC（%JDK_HOME%\bin\jmc.exe），打开此程序，会发现它是一个典型的Eclipse RCP应用。本文简单的介绍如何使用JMC来监控、记录JVM的运行过程。 目标JVM配置 注意：你看到的基于Eclipse的JMC用户界面，是一个前端的工具，在被监控的JVM（目标JVM）上需要开启以下Java Options才能对其进行监控、进行黑匣子记录。 [crayon-69d7a7be654b3841327896/] 如果要在目标JVM上启动持续不断的黑匣子记录，并在JVM正常退出时Dump记录为文件，可以参考下面的脚本设置JVM参数： [crayon-69d7a7be654ba688075246/] 连接到目标JVM 配置并重启目标JVM后，打开JMC，点击 File <a class="read-more" href="https://blog.gmem.cc/jvm-monitoring-with-oracle-jmc">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/jvm-monitoring-with-oracle-jmc">使用Oracle Java Mission Control监控JVM运行状态</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">简介</span></div>
<p>Oracle  Java Mission Control（以下称JMC）是一个集成到JVM（jdk7u40+）的性能剖析和诊断工具，相比起JProfiler之类的性能剖析工具，JMC更加简单易用，界面友好。</p>
<p>JMC使用了JVM内部特定的基于事件的接口，不同于一般性能剖析工具使用JVMPI/JVMTI方式实现。因此JMC几乎不会给应用造成额外的压力，可以用在负载很高的生产环境中：</p>
<ol>
<li>JFR在默认设置continuous下运行几乎对性能没有影响</li>
<li>JFR在默认设置profiling下运行通常造成小于2%的性能下降</li>
</ol>
<p>在<a href="http://www.oracle.com/technetwork/articles/javase/index-jsp-138363.html" target="_blank">JDK 7 Update 40</a>及其以后的版本中已经集成了JMC（%JDK_HOME%\bin\jmc.exe），打开此程序，会发现它是一个典型的Eclipse RCP应用。本文简单的介绍如何使用JMC来监控、记录JVM的运行过程。</p>
<div class="blog_h1"><span class="graybg">目标JVM配置</span></div>
<div>注意：你看到的基于Eclipse的JMC用户界面，是一个前端的工具，在被监控的JVM（目标JVM）上需要开启以下Java Options才能对其进行监控、进行黑匣子记录。</div>
<pre class="crayon-plain-tag">-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=7777
-Dcom.sun.management.jmxremote
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder</pre>
<p>如果要在目标JVM上启动持续不断的黑匣子记录，并在JVM正常退出时Dump记录为文件，可以参考下面的脚本设置JVM参数：</p>
<pre class="crayon-plain-tag">for /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set md=%%a-%%b-%%c)
for /f "tokens=1-3 delims=/:." %%a in ("%TIME%") do (set mt=%%a%%b%%c)
set CUR_TIME=%md%-%mt%

rem 启用黑匣子默认记录行为。官方文档注明dumponexitpath支持目录，但我在7u71版本下测试失败
set JAVA_OPTS=%JAVA_OPTS% -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=%LOG_DIR%\jfr\dump-on-exit-%CUR_TIME%.jfr,maxage=3600s,settings=%JRE_HOME%\lib\jfr\profile.jfc</pre>
<div class="blog_h1"><span class="graybg">连接到目标JVM</span></div>
<p>配置并重启目标JVM后，打开JMC，点击<span style="background-color: #c0c0c0;"> File - Connect... - Create New connection</span>，参考下图设置，完毕后点击Test connection确认可以连通，最后点击Finish结束配置。</p>
<p><img src="https://blog.gmem.cc/wp-content/uploads/2014/11/jmc-1.jpg" alt="" width="100%" /></p>
<div class="blog_h1"><span class="graybg">MBean Server</span></div>
<p>在左侧窗格JVM Browser视图中，双击刚刚创建的JMC连接，点击MBean Server，即可在右侧主窗体查看实时的JVM状态信息，供6个选项卡，下面依次描述。</p>
<div class="blog_h2"><span class="graybg">总览</span></div>
<p>包含JVM概要性的实时图表，包含3个面板：</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 250px; text-align: center;">面板 </td>
<td style="text-align: center;"> 说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>仪表盘（Dashboard）</td>
<td>
<p>以仪表方式显示系统运行参数，默认显示堆内存占用、JVM处理器占用、垃圾回收前后的堆内存情况。注意仪表上有有两个指针，灰色的通常显示最大值，黑色的显示当前值。</p>
<p>面板右侧的+号按钮，点击后可以添加目标JVM支持的任何运行参数到仪表盘中</p>
</td>
</tr>
<tr>
<td>处理器（Processor）</td>
<td>显示JVM、操作系统的动态CPU占用曲线</td>
</tr>
<tr>
<td>内存（Memory）</td>
<td>默认显示Java堆内存占用情况，可以选择查看物理内存占用等项目</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">MBean浏览器</span></div>
<p>以树形结构显示目标JVM支持的所有MBean列表和属性、操作集。</p>
<div class="blog_h2"><span class="graybg">触发器</span></div>
<p>包含若干预定义的触发器，可以在<span style="background-color: #c0c0c0;">特定条件下，执行预定义的动作</span>。支持的触发器包括：</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 250px; text-align: center;"> 触发器</td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>CPU Usage - JVM Process (Too High)</td>
<td>当JVM的进程的CPU占用过高时</td>
</tr>
<tr>
<td>CPU Usage - JVM Process (Too Low)</td>
<td>当JVM的进程的CPU占用过低时</td>
</tr>
<tr>
<td>CPU Usage - Machine (Too High)</td>
<td>当OS的CPU占用过高时</td>
</tr>
<tr>
<td>CPU Usage - Machine (Too Low)</td>
<td>当OS的CPU占用过低时</td>
</tr>
<tr>
<td>Deadlocked Threads</td>
<td>当发生JVM线程死锁时</td>
</tr>
<tr>
<td>Live Set (Too Large)</td>
<td>当垃圾回收之后，存活对象占堆大小百分比过大时</td>
</tr>
<tr>
<td>Thread Count (Too High)</td>
<td>当JVM线程总数过大时</td>
</tr>
</tbody>
</table>
<p>此外，任何MBean属性均可以作为触发器使用，中间件（例如Tomcat、Weblogic、ActiveMQ）都有自己的扩展。 双击触发器后，右侧即显示规则详情（Rule Details），可以定义触发的阈值（到达时，或者从异常值恢复时）、执行的动作，可用的动作包括：</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 250px; text-align: center;"> 动作</td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>Application alert</td>
<td>在应用程序上显示一个警告对话框</td>
</tr>
<tr>
<td>Console output</td>
<td>在控制台（stdout）上输出警告信息</td>
</tr>
<tr>
<td>Dump Flight Recording</td>
<td>保存黑匣子记录内容</td>
</tr>
<tr>
<td>HPROF Dump</td>
<td>保存堆镜像</td>
</tr>
<tr>
<td>Log to file</td>
<td>在日志文件中输出警告信息</td>
</tr>
<tr>
<td>Send e-mail</td>
<td>通过电子邮件发送警告信息</td>
</tr>
<tr>
<td>Start Continuous Flight Recording</td>
<td>启动不间断的黑匣子记录</td>
</tr>
<tr>
<td>Start Time Limited Flight Recording</td>
<td>启动限制时间长度的黑匣子记录</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">LiveSet</span></div>
<p>所谓LiveSet，是指在一次<span style="background-color: #c0c0c0;">垃圾回收之后，堆内存的占用比率</span>，取值在0-1之间。</p>
<p>如果GC后，可用的内存空间不足，则LiveSet接近100%，这预示可能存在OOM风险。在生产环境下，我们可以监控LiveSet，并在其过大时，把堆内存映像Dump出来供后续分析。</p>
<p>触发器配置示例：</p>
<p><a href="https://blog.gmem.cc/wp-content/uploads/2014/11/liveset-trigger-1.png"><img class="aligncenter  wp-image-19045" src="https://blog.gmem.cc/wp-content/uploads/2014/11/liveset-trigger-1.png" alt="liveset-trigger-1" width="924" height="372" /></a></p>
<p><a href="https://blog.gmem.cc/wp-content/uploads/2014/11/liveset-trigger-2.png"><img class="aligncenter wp-image-19047" src="https://blog.gmem.cc/wp-content/uploads/2014/11/liveset-trigger-2.png" alt="liveset-trigger-2" width="925" height="295" /></a></p>
<p>其中Condition面板：</p>
<ol>
<li>Current Value为指标的当前值，当发生GC后，自动刷新</li>
<li>Max trigger value为触发器激活时的指标值</li>
<li>Sustained period，指标必须到达Max trigger value至少多长时间，触发器才可能激活</li>
<li>Limit period，连续两次激活触发器的最小间隔时间</li>
</ol>
<p>其中Action面板：</p>
<ol>
<li>Only live，如果勾选，仅仅GCRoot可达的对象才被Dump出来</li>
<li>hprof路径为服务器的路径</li>
</ol>
<p>其中Constraints面板：可以指定此触发器在什么日期、什么时间段启用。</p>
<p>要分析内存映像，你可以使用如下命令启动一个Web UI：</p>
<pre class="crayon-plain-tag">jhat -port 7770 -J-Xmx4G default.hprof</pre>
<div class="blog_h2"><span class="graybg">系统</span></div>
<p>显示JVM和系统的概要信息，包含3个面板：</p>
<ol>
<li>系统信息：例如OS类型、硬件架构、系统内存、JVM的PID、JVM版本、Classpath、JVM启动时间、JVM参数（Java Options）</li>
<li>JVM统计：例如已加载的类数量、已运行时间</li>
<li>系统属性：显示JVM的系统属性</li>
</ol>
<div class="blog_h2"><span class="graybg">内存</span></div>
<p>显示JVM内存占用情况，分为上下两个面板。</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 250px; text-align: center;">面板</td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>GC Table</td>
<td>
<p>显示垃圾回收器（ParNew：新生代的并行回收器，ConcurrentMarkSweep：并发垃圾回收器…）的工作情况，包括：GC总计时间、GC总次数、最近GC开始结束时间、GC标识符、GC线程数</p>
</td>
</tr>
<tr>
<td>Active Memory Pools</td>
<td>
<p>显示当前的内存池的大小、已用大小、类型（堆/非堆），可能有以下内存池：</p>
<ol>
<li>Code Cache：代码缓存</li>
<li>Par Eden Space：并行（-XX:+UseParNewGC）垃圾回收的新生代Eden区</li>
<li>Par Survivor Space：并行垃圾回收的新生代Survivor区</li>
<li>CMS Perm Gen：并发垃圾回收永久代</li>
<li>CMS Old Gen：并发垃圾收集年老代</li>
<li>PS Old Gen：并行（-XX:+UseParallelGC）垃圾收集年老代</li>
</ol>
<p>关于垃圾回收器内存分代，参考：<a href="/jvm-options-and-performance-tuning" target="_blank">JVM参数与性能调优</a></p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h2"><span class="graybg">线程</span></div>
<p>显示JVM线程活动情况，分为三个面板。</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 250px; text-align: center;">面板</td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>Live Thread Graph</td>
<td>
<p>显示当前存活线程的数量、守护线程的数量、线程数量峰值的实时曲线</p>
</td>
</tr>
<tr>
<td>Live Threads</td>
<td>
<p>显示当前存活线程的列表，可以进行CPU占用分析、死锁检测、线程分配内存量的分析</p>
</td>
</tr>
<tr>
<td>Stack traces for selected threads</td>
<td>显示瞬时的线程调用栈</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">启动黑匣子</span></div>
<p>正如民航的黑匣子一样，JMC的这个功能，可以用于事后分析系统性能低下，甚至崩溃的原因。JMC支持两种方式来启动黑匣子记录：通过触发器自动启动， 或者在左侧面板，双击Flight Recorder，手工启动。手工启动可以参考下图设置：<a href="/wp-content/uploads/2014/11/jmc-2.jpg"><img class="size-full wp-image-2552 aligncenter" src="https://blog.gmem.cc/wp-content/uploads/2014/11/jmc-2.jpg" alt="jmc-2" width="793" height="626" /></a></p>
<p>其中：Time fixed recording表示<span style="background-color: #c0c0c0;">记录定长时间</span>，时间到达后，自动停止记录；Continuous recording表示进行<span style="background-color: #c0c0c0;">持续不断的记录</span>，直到JVM退出或者接收到停止指令，这种记录方式下可以随时进行dump操作。</p>
<p>虽然黑匣子在JVM本地记录数据，但不在Java堆中记录，因此它并不会影响内存特性和垃圾收集。</p>
<p>黑匣子录制完成后，会在你选择的目录中生成一个.jfr文件，该文件包含录制期间JVM中发生的各种事件。</p>
<div class="blog_h2"><span class="graybg">工作机制</span></div>
<p>黑匣子通过JVM内部API来收集数据，并存放在一个线程本地（thread-local）的缓冲中，并最终刷入全局内存缓冲（global in-memory buffer），内存缓冲中的数据，会被刷入磁盘，磁盘文件时经过压缩的。每个记录数据块，要么在内存中，要么在磁盘中，这意味着——进程被停止或者宕机时，部分数据会丢失，JVM崩溃会也可能导致一部分数据丢失。</p>
<p>可以配置黑匣子不使用磁盘空间，这种场景下，全局内存缓冲被循环使用，<span style="background-color: #c0c0c0;">旧的数据自动丢弃</span>。</p>
<div class="blog_h2"><span class="graybg">黑匣子记录模板</span></div>
<p>在JMC界面上，点击 Windows - Flight Recording Template Manager，看到类似如下界面。可以导入、导出、编辑JFR的设置文件。</p>
<p><a href="/wp-content/uploads/2014/11/jmc-5.jpg"><img class="size-full wp-image-2658 aligncenter" src="https://blog.gmem.cc/wp-content/uploads/2014/11/jmc-5.jpg" alt="jmc-5" width="768" height="600" /></a></p>
<p>我们可以导入%JDK_HOME%\jre\lib\jfr下的两个自带模板：default.jfc（Continuous）、profile.jfc（Profiling）。这两个模板的对比如下：</p>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 150px; text-align: center;"> 模板</td>
<td style="text-align: center;">特性 </td>
</tr>
</thead>
<tbody>
<tr>
<td> Continuous</td>
<td>
<p>Garbage Collector:正常<br />Compiler:正常<br />Method Sampling: 正常<br />Thread Dump: 最少一次<br />Exceptions:仅Error<br />Synchronization Threshold: 20 ms<br />File I/O Threshold: 20 ms<br />Socket I/O Threshold: 20 ms<br />Heap Statistics: 禁用<br />Class Loading:禁用<br />Allocation Profiling:禁用</p>
<p>未启用记录的事件类型：Exception Throw、<span style="background-color: #c0c0c0;">Object Alloc In New TLAB、Object Alloc Outside TLAB</span>、Class Loading、<span style="background-color: #c0c0c0;">Compile/Failure</span>、GC/Object Count、GC/Object Count After GC、GC/Phases/Phase Level 3、Profiling/Execution Sample Info、</p>
</td>
</tr>
<tr>
<td> Profiling</td>
<td>
<p>Garbage Collector:正常<br />Compiler:详细<br /><span style="background-color: #c0c0c0;">Method Sampling: 最大化</span><br /><span style="background-color: #c0c0c0;">Thread Dump: 每分钟</span><br />Exceptions:仅Error<br /><span style="background-color: #c0c0c0;">Synchronization Threshold: 10 ms</span><br /><span style="background-color: #c0c0c0;">File I/O Threshold: 10 ms</span><br /><span style="background-color: #c0c0c0;">Socket I/O Threshold: 10 ms</span><br />Heap Statistics: 禁用<br />Class Loading:禁用<br /><span style="background-color: #c0c0c0;">Allocation Profiling:启用</span></p>
<p>未启用记录的事件类型：Exception Throw、Class Loading、GC/Object Count、GC/Object Count After GC、GC/Phases/Phase Level 3、Profiling/Execution Sample Info、</p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">黑匣子诊断命令</span></div>
<p>利用诊断命令，可以通过脚本控制黑匣子的行为，命令的示例如下：</p>
<pre class="crayon-plain-tag">rem 获取进程号为5361的JVM关于JFR.start命令的帮助
jcmd 5361 help JFR.start

rem 检查进程的JFR运行状态
jcmd 7648 JFR.check
rem 输出如下。注意recording=0表示正在运行的记录的标识符，后续操作需要用到这个标识符
rem 7648:
rem Recording: recording=0 name="HotSpot default" maxage=1h (running)

rem 启动一个15分钟的黑匣子记录，延迟5分钟启动，使用JDK自带的默认设置（default.jfc），保存Dump文件到D盘
jcmd 7648 JFR.start name=SampleRcd delay=300 duration=900s filename=D:\temp\SampleRcd.jfr 
     \ settings=D:\JavaEE\jdk\x64\jre\lib\jfr\default.jfc

rem 相对路径取决于目标JVM
jcmd 1234 JFR.start delay=0s duration=${jfr_du}s name=$name filename=$PWD/$name.jfr settings=profile

rem 下面的脚本，可以用于定期进行记录，按记录时间保存为不同的文件
setlocal
set DUMP_DIR=D:\temp
set SERVICE_NAME=Tomcat7
set JAVA_HOME=D:\JavaEE\jdk\x64\1.7
pushd %JAVA_HOME%\bin
for /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set md=%%a-%%b-%%c)
for /f "tokens=1-3 delims=/:." %%a in ("%TIME%") do (set mt=%%a%%b%%c)
set CUR_TIME=%md%-%mt%
for /F "tokens=1,3" %%a in ('sc queryex %SERVICE_NAME%') do (
    if "%%a" == "PID" set "JPID=%%b"
)

rem 启动飞行记录，如果目标JVM是以SYSTEM身份启动的NT Service，可以使用PSTools发起jcmd命令，否则会报错：insufficient memory or insufficient privileges to attach
rem psexec -s jcmd %JPID% JFR.start ...
jcmd %JPID% JFR.start name=rcd-%CUR_TIME% duration=900s compress=true filename=%DUMP_DIR%\rcd-%CUR_TIME%.jfr settings=%JAVA_HOME%\jre\lib\jfr\profile.jfc
popd
endlocal

rem 导出JFR的Dump文件
rem 如果目标JVM正在在运行持续不断的黑匣子记录，使用该命令，再结合定时任务机制，可以定期保存黑匣子记录的Dump文件
jcmd 7648 JFR.dump recording=0 filename=F:\temp\dump.jfr</pre>
<div class="blog_h2"><span class="graybg">命令列表</span></div>
<table style="width: 100%;" border="1" cellspacing="0" cellpadding="5">
<thead>
<tr>
<td style="width: 150px; text-align: center;"> 命令</td>
<td style="text-align: center;">说明 </td>
</tr>
</thead>
<tbody>
<tr>
<td>JFR.start</td>
<td>
<p>启动一个JFR（黑匣子记录）实例，参数：</p>
<p>name 本次记录的名称<br />settings 服务器上的设置模板<br />defaultrecording 是否启动默认录制<br />delay 录制延迟时间，默认0s<br />duration 录制持续时间，默认0s，表示无限<br />filename 录制文件的名称<br />compress 是否使用GZip压缩结果，默认否<br />maxage 数据最大生命周期，默认0s，表示无限制<br />maxsize 数据最大字节数，默认0，表示无限制</p>
</td>
</tr>
<tr>
<td>JFR.check</td>
<td>
<p>显示运行中的JFR的状态，参数：</p>
<p>name 记录名称<br />recording 记录标识符<br />verbose 打印冗余信息，默认否</p>
</td>
</tr>
<tr>
<td>JFR.stop</td>
<td>
<p>停止运行中的JFR，参数：</p>
<p>name 记录名称<br />recording 记录标识符<br />discard 是否丢弃录制数据<br />filename 拷贝录制数据到文件</p>
</td>
</tr>
<tr>
<td>JFR.dump</td>
<td>
<p>将录制中的JFR保存到文件，参数：</p>
<p>name 记录名称<br />recording 记录标识符<br />filename 拷贝录制数据到文件</p>
</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">黑匣子分析</span></div>
<p>打开黑匣子记录的.jfr文件，即可看到类似下面的界面：左侧是记录的不同视图，可以点击切换；右侧主面板，顶部是事件的时间轴，<span style="background-color: #c0c0c0;">拖动滑块，可以改变聚焦的时间范围（勾选右边的同步选择可以在切换视图时保持聚集范围）</span>，底部有若干选项卡。</p>
<p><a href="/wp-content/uploads/2014/11/jmc-3.jpg"><img class="alignnone  wp-image-2582" src="https://blog.gmem.cc/wp-content/uploads/2014/11/jmc-3.jpg" alt="jmc-3" width="917" height="653" /></a></p>
<p>下面，按照视图分别描述。</p>
<div class="blog_h2"><span class="graybg">基本信息</span></div>
<p>包含4个选项卡：</p>
<div class="blog_h3"><span class="graybg">总览</span></div>
<p style="padding-left: 30px;">可以看到聚焦时间范围内的实时仪表（堆占用、CPU占用、GC停顿时间），以及CPU、堆使用情况的曲线图。</p>
<div class="blog_h3"><span class="graybg">JVM信息</span></div>
<p style="padding-left: 30px;">可以看到JVM的一些基本信息，包括启动时间、JVM参数等。</p>
<div class="blog_h3"><span class="graybg">系统属性</span></div>
<p style="padding-left: 30px;">可以看到JVM的系统属性列表</p>
<div class="blog_h3"><span class="graybg">记录</span></div>
<p style="padding-left: 30px;">可以显示记录的事件的列表</p>
<div class="blog_h3"><span class="graybg">内存</span></div>
<p>包含6个选项卡</p>
<div class="blog_h3"><span class="graybg">总览</span></div>
<p style="padding-left: 30px;">Memory Usage：可以显示聚焦时间范围内OS总内存、OS已使用内存、提交的堆、使用的堆的大小曲线图。</p>
<p style="padding-left: 30px;">GC Configuration：显示简单的GC配置</p>
<p style="padding-left: 30px;">GC Statistics：显示简单的GC统计，包括垃圾回收次数、停顿时间</p>
<div class="blog_h3"><span class="graybg">垃圾收集</span></div>
<p style="padding-left: 30px;">上面的面板，包含4个选项卡：</p>
<p style="padding-left: 60px;">Heap：堆的使用情况曲线，红色小柱形显示了GC停顿的持续时间（刻度在右边）</p>
<p style="padding-left: 60px;">Reference Objects：包含软引用、弱引用、幻引用、一般引用的数量变化区域图</p>
<p style="padding-left: 60px;">Failed Promotions：失败的晋升列表，所谓晋升是指：年轻代对象向年老代转移的GC动作，包含对象个数和大小等信息</p>
<p style="padding-left: 60px;">Failed Evacuations：</p>
<p style="padding-left: 30px;">下面的面板，左侧显示历次GC的列表，右侧显示单次GC的详细信息，如下：</p>
<p style="padding-left: 60px;">General：显示GC类型、触发原因、ID、开始结束时间、暂停时间</p>
<p style="padding-left: 60px;">GC Phase：GC每个步骤的开始和持续时间</p>
<p style="padding-left: 60px;">Reference Objects：本次GC涉及的各类引用的数量</p>
<p style="padding-left: 60px;">Heap：堆在GC前后的大小对比</p>
<p style="padding-left: 60px;">Perm Gen：永久代在GC前后的大小对比</p>
<div class="blog_h3"><span class="graybg">垃圾回收时间</span></div>
<p style="padding-left: 30px;">显示各代、各次GC所消耗的时间</p>
<div class="blog_h3"><span class="graybg">垃圾回收配置</span></div>
<p style="padding-left: 30px;">显示GC的详细配置，包括GC基本配置、堆的配置、年轻代的配置</p>
<div class="blog_h3"><span class="graybg"> 内存分配</span></div>
<p>显示聚焦时间范围内的内存分配统计信息</p>
<p style="padding-left: 30px;">General：在线程<span style="background-color: #c0c0c0;">本地分配缓冲（TLAB）内、外（即Eden区域）</span>中分配的对象个数、内存大小。面板下部是内存分配大小按时间的柱形图</p>
<p style="padding-left: 30px;">Allocation in new TLAB：在TLAB中分配的内存，按对象类型、或者按执行分配的线程的占比饼图；Allocation Profile可以剖析分配内存热点所在的调用栈</p>
<p style="padding-left: 30px;">Allocation outside TLAB：在Eden区域的内存分配情况，包含的子选项卡同上</p>
<p>示例：</p>
<p><a href="https://blog.gmem.cc/wp-content/uploads/2014/11/jfr-memory-alloc.png"><img class="aligncenter wp-image-19061" src="https://blog.gmem.cc/wp-content/uploads/2014/11/jfr-memory-alloc.png" alt="jfr-memory-alloc" width="927" height="709" /></a></p>
<p>在Allocation By Class选项卡中：</p>
<ol>
<li>上面板Allocation Pressure，按对象类型，显示内存占用最大的对象</li>
<li>下面板Stack Trace，选中上面板的某个对象类型后，在此显示分配对象的调用栈。第一行为直接分配对象的代码</li>
</ol>
<div class="blog_h3"><span class="graybg">对象统计</span></div>
<p style="padding-left: 30px;">显示对象数量和内存占用的统计信息，包含上下两部分</p>
<p style="padding-left: 30px;">上面的面板：显示占有堆内存百分比大于0.5%的类型的列表</p>
<p style="padding-left: 30px;">下面的面板：显示增长数量最快的类型的列表</p>
<div class="blog_h2"><span class="graybg">代码</span></div>
<p>包含6个选项卡：</p>
<div class="blog_h3"><span class="graybg">总览</span></div>
<p style="padding-left: 30px;">显示占用CPU时间最多的代码，分为上下两部分</p>
<p style="padding-left: 30px;">上面的面板：显示CPU时间占用最多的包，包括列表和饼图</p>
<p style="padding-left: 30px;">下面的面板：显示CPU占用最多的类，按占比降序排列</p>
<div class="blog_h3"><span class="graybg">热点方法</span></div>
<p style="padding-left: 30px;">显示热点方法（CPU占用时间最多），按占比降序排列，点击左侧小箭头可以向下钻取（找到哪些代码调用了这个方法导致的热点）</p>
<div class="blog_h3"><span class="graybg">调用树</span></div>
<p style="padding-left: 30px;">类似于热点方法选项卡，但是会显示所有热点方法的完整调用栈</p>
<div class="blog_h3"><span class="graybg">异常</span></div>
<p style="padding-left: 30px;">包含3个选项卡，显示异常（包括错误）的统计信息</p>
<p style="padding-left: 30px;">Overview：显示异常和错误的总数、最频繁发生异常的调用栈</p>
<p style="padding-left: 30px;">Exceptions、Error：单独显示异常或者错误的总数、频繁调用栈，注意，异常默认是不记录的</p>
<div class="blog_h3"><span class="graybg">编译</span></div>
<p style="padding-left: 30px;">显示即时编译的次数、编译大小、失败的日志</p>
<div class="blog_h3"><span class="graybg">类加载</span></div>
<p style="padding-left: 30px;">显示按时间的类加载、卸载的数量曲线图</p>
<div class="blog_h2"><span class="graybg">线程</span></div>
<div class="blog_h3"><span class="graybg">总览</span></div>
<p style="padding-left: 30px;">分为上下两部分：</p>
<p style="padding-left: 30px;">上面的面板：显示OS、JVM的CPU占用率的按时间统计的区域图</p>
<p style="padding-left: 30px;">下面的面板：显示守护线程、活动线程数量的曲线图</p>
<div class="blog_h3"><span class="graybg">热点线程</span></div>
<p style="padding-left: 30px;">显示CPU占用最多的线程，及选中线程的热点方法，分为上下两部分</p>
<p style="padding-left: 30px;">上面的面板：显示CPU占用最多的线程，按占比降序排列</p>
<p style="padding-left: 30px;">下面的面板：显示上面板选中线程的热点方法、调用栈 </p>
<div class="blog_h3"><span class="graybg">资源争用</span></div>
<p style="padding-left: 30px;">显示因为锁争用导致的线程阻塞的统计信息，分为3个选项卡：</p>
<p style="padding-left: 60px;">Top Blocking Locks：发生阻塞最多的监视器（锁）对象的列表，包含了锁定次数、最长时间</p>
<p style="padding-left: 60px;">Top Blocked Threads：因为等待锁被阻塞时间最长的线程的列表</p>
<p style="padding-left: 60px;">Top Blocking Threads：因为占用锁导致其他线程等待时间最长的线程的列表</p>
<div class="blog_h3"><span class="graybg">延迟</span></div>
<p style="padding-left: 30px;">显示因为：Java线程休眠、监视器等待、Socket读取、监视器阻塞等原因导致的线程执行延迟的情况，包括延迟信息的列表和饼图，已经导致延迟的线程调用栈。延迟相关的事件包括：Java Thread Park（Waiting）、Java Monitor Wait（等待被唤醒）、Java Monitor  Blocked（积极进入同步区被阻塞）等。</p>
<div class="blog_h3"><span class="graybg">线程栈Dump</span></div>
<p style="padding-left: 30px;">包含定时捕获的JVM中所有线程的瞬时调用栈镜像</p>
<div class="blog_h3"><span class="graybg">监视器实例</span></div>
<p style="padding-left: 30px;">Lock Instances：监视器对象的列表，包含锁定次数、总计持续时间</p>
<p style="padding-left: 30px;">Trace Tree：选中监视器对象的锁定调用栈，每个调用栈锁定的次数</p>
<p style="padding-left: 30px;">Top Threads：占用监视器次数最多的线程列表</p>
<div class="blog_h2"><span class="graybg">输入输出</span></div>
<div class="blog_h3"><span class="graybg">总览</span></div>
<p style="padding-left: 30px;">分为两个选项卡</p>
<p style="padding-left: 30px;">File Overview：</p>
<p style="padding-left: 60px;">File Reads and Writes：显示按时间读写文件字节数的曲线</p>
<p style="padding-left: 60px;">File Read、File Write：显示针对具体文件的读写字节数、次数的列表</p>
<p style="padding-left: 30px;">Socket Overview：</p>
<p style="padding-left: 60px;">Socket Read and Writes：显示按时间读写Socket字节数的曲线</p>
<p style="padding-left: 60px;">Socket  Read、Socket Writes：显示针对具体目标主机、端口读写字节数、次数的列表</p>
<div class="blog_h3"><span class="graybg">读文件</span></div>
<p>按文件、线程、事件统计文件读操作的列表，以及每个文件读取按时间的变化、线程调用栈</p>
<div class="blog_h3"><span class="graybg">写文件</span></div>
<p>按文件、线程、事件统计文件写操作的列表，以及每个文件写入按时间的变化、线程调用栈</p>
<div class="blog_h3"><span class="graybg">读Socket</span></div>
<p>按目标主机、线程、事件统计文Socket读操作的列表，以及每个Socket读取按时间的变化、线程调用栈</p>
<div class="blog_h3"><span class="graybg">写Socket</span></div>
<p>按目标主机、线程、事件统计文Socket写操作的列表，以及每个Socket写入按时间的变化、线程调用栈</p>
<div class="blog_h2"><span class="graybg">系统</span></div>
<div>包含操作系统和硬件的基本信息</div>
<div class="blog_h2"><span class="graybg">事件</span></div>
<p>显示黑匣子记录的事件的相关信息，<span style="background-color: #c0c0c0;">左侧面板Event Types可以过滤</span>关注的事件类型。总体来说，事件可以分为三类：<span style="background-color: #c0c0c0;">持续事件</span>（duration，持续一段时间，例如GC事件）；<span style="background-color: #c0c0c0;">瞬时事件</span>（instant，立即发生和结束，例如内存溢出）；<span style="background-color: #c0c0c0;">样本事件</span>（sample，通过定期采样获取，例如栈dump）。</p>
<div class="blog_h3"><span class="graybg">总览</span></div>
<p>Producers：显示事件生产者的列表，以及制造事件的占比饼图</p>
<p style="padding-left: 30px;">Event Types：显示各类型事件持续总时间、次数，占比饼图</p>
<div class="blog_h3"><span class="graybg">日志</span></div>
<p style="padding-left: 30px;">显示每一个事件的记录，按时间排列，为每个事件显示：开始时间、结束时间、持续时间、产生事件的线程</p>
<div class="blog_h3"><span class="graybg">图表</span></div>
<p style="padding-left: 30px;">以时间轴的形式展示事件历史</p>
<div class="blog_h3"><span class="graybg">线程</span></div>
<p style="padding-left: 30px;">以列表形式展示各线程产生事件的数量、持续时间</p>
<div class="blog_h3"><span class="graybg">调用栈跟踪</span></div>
<p style="padding-left: 30px;">按产生事件持续时间长短，降序排列相关的调用栈</p>
<div class="blog_h3"><span class="graybg">事件统计</span></div>
<p style="padding-left: 30px;">可以按单个事件类型进行简单的统计分析，支持不同的分组方式，支持总数、平均数、次数等指标，选中单个统计结果，可以显示调用栈。</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/jvm-monitoring-with-oracle-jmc">使用Oracle Java Mission Control监控JVM运行状态</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/jvm-monitoring-with-oracle-jmc/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
