我们的垃圾回收日志分析 REST API 提供了作用强大的微指标。借助这些微指标,您可对程序的可用性和性能特征进行预测。
观看下方的短视频以了解如何使用我们的 API。
如何调用垃圾回收日志分析 API?
垃圾回收日志分析功能的调用非常简单:
- 注册即可。我们会通过邮件向您发送 API Key。这是一次性的设置过程。注意:如果您购买了带有 API 的企业版本,则不需要进行注册。API Key 将随安装说明一并提供。
- Post HTTP 请求至 https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}
- HTTP 请求的主体中应包含需要分析的垃圾回收日志。
- HTTP 响应将以 JSON 格式回传。JSON 文件中将包含有关 GC 日志的多种重要数据。可在 JSON 响应中查找的主要元素是:“isProblem”。如果发现任何内存/性能问题,则该元素的值将为“true”。“problem”元素中将包含内存问题的详细描述。
CURL 命令
假设您的 Java GC 日志文件位于“./my-app-gc.log”,那么调用 API 的 CURL 命令为:
curl -X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY} --header "Content-Type:text"
好像不能再简单了,对吧?
压缩
GC 日志文件通常会很大。为了快速高效地进行处理,我们建议您对 GC 日志文件进行压缩后再发送。压缩 GC 日志时,您需要在 HTTP Header 元素或 URL 参数中传递“Content-Encoding”元素。
如果您想将 GC 日志文件压缩为“zip”格式,则可使用 HTTP Header 元素来调用 API
curl -X POST --data-binary @./my-app-gc.zip "https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}" --header "Content-Type:text" --header "Content-Encoding:zip"
也可在 URL 参数中使用“Content-Encoding”来调用 API
curl -X POST --data-binary @./my-app-gc.zip "https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&Content-Encoding=zip" --header "Content-Type:text"
我们支持以下压缩格式:
zip、gz、xz、z、lzma、deflate、sz、lz4、zstd、bz2、tar
您可根据自身需求进行选择。无论选择何种 GC 日志文件压缩格式,只需传递相应的“Content-Encoding”元素即可。
备注:可在 CURL 中使用“–data-binary”来取代“–data”选项。“–data”请求中不会保留新的换行符。新换行符应当保留以确保解析正常进行。
从远程位置下载 GC 日志
如果您的 Java GC 日志文件存储在了远程位置——如 AWS S3 存储桶中,那么在需要对 GC 日志进行分析时,您就必须将文件下载到本地计算机,然后再调用 API。为了简化这一过程并实现自动化,我们在 API 中引入了“location”参数。您可向“location”位置传递 http(s) URL 位置以调用 API。此时,API 将从远程位置下载文件,然后对其中的数据进行分析并返回响应。如需了解详情请参阅本文。
curl -X POST "https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&location={GC-LOG-HTTP-URL}" --header "Content-Type:text"
其他工具
您也可以使用任意网络服务客户端工具(如:SOAP UI、PostMan Browser Plugin 等)来调用 API

图:通过 PostMan 插件发布 GC 日志
示例响应
{
{
"isProblem": true,
"problem": [
"分析表明您的程序中出现连续 Full GC。这可能会导致间歇性的 OutOfMemoryErrors 错误、响应速度下降或高 CPU 消耗,甚至使应用程序无响应。"
"我们的分析显示,您的应用程序正在遭受长时间 GC 活动的折磨。4 个 GC 事件耗时超过 10 秒。长时间运行的 GC 对于程序性能有负面影响。"
"应用程序线程已停止超过 10 秒 342 次。"
],
"jvmHeapSize": {
"youngGen": {
"allocatedSize": "7.5 gb",
"peakSize": "6 gb"
},
"oldGen": {
"allocatedSize": "22.5 gb",
"peakSize": "22.5 gb"
},
"metaSpace": {
"allocatedSize": "1.04 gb",
"peakSize": "48.52 mb"
},
"total": {
"allocatedSize": "30 gb",
"peakSize": "28.5 gb"
}
},
"gcStatistics": {
"totalCreatedBytes": "249.49 gb",
"measurementDuration": "7 hrs 32 min 52 sec",
"startTimestamp": "2018-12-15T15:58:37.622+0100",
"endTimestamp": "2018-12-15T15:58:44.622+0100",
"avgAllocationRate": "9.4 mb/sec",
"avgPromotionRate": "1.35 mb/sec",
"minorGCCount": "62",
"minorGCTotalTime": "1 min 19 sec",
"minorGCAvgTime": "1 sec 274 ms",
"minorGCAvgTimeStdDeviation": "2 sec 374 ms",
"minorGCMinTIme": "0",
"minorGCMaxTime": "13 sec 780 ms",
"minorGCIntervalAvgTime": "7 min 25 sec 442 ms",
"fullGCCount": "166",
"fullGCTotalTime": "14 min 11 sec 620 ms",
"fullGCAvgTime": "5 sec 130 ms",
"fullGCAvgTimeStdDeviation": "5 sec 207 ms",
"fullGCMinTIme": "120 ms",
"fullGCMaxTime": "57 sec 880 ms",
"fullGCIntervalAvgTime": "2 min 19 sec 104 ms"
},
"gcKPI": {
"throughputPercentage": 99.952,
"averagePauseTime": 750.232,
"maxPauseTime": 57880
},
"gcDurationSummary": {
"groups": [
{
"start": "0",
"end": "6",
"numberOfGCs": 212
},
{
"start": "6",
"end": "12",
"numberOfGCs": 4
},
{
"start": "12",
"end": "18",
"numberOfGCs": 2
},
{
"start": "42",
"end": "48",
"numberOfGCs": 1
},
{
"start": "54",
"end": "60",
"numberOfGCs": 1
}
]
},
"gcCauses": [
{
"cause": "分配失败",
"count": 57
},
{
"cause": "并发模式失败",
"count": 162
},
{
"cause": "Full GC - 分配失败",
"count": 369
}
],
"commandLineFlags": " -XX:CMSInitiatingOccupancyFraction=65 -XX:+CMSScavengeBeforeRemark -XX:CMSWaitDuration=2000 -XX:ConcGCThreads=8 -XX:+DisableExplicitGC -XX:GCLogFileSize=104857600 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=32212254720 -XX:InitialTenuringThreshold=4 -XX:+ManagementServer -XX:MaxHeapSize=32212254720 -XX:MaxTenuringThreshold=4 -XX:NewRatio=3 -XX:NumberOfGCLogFiles=10 -XX:OldPLABSize=16 -XX:ParGCCardsPerStrideChunk=32768 -XX:+PrintClassHistogram -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintPromotionFailure -XX:+PrintTenuringDistribution -XX:SurvivorRatio=3 -XX:ThreadStackSize=334 -XX:+UnlockDiagnosticVMOptions -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseGCLogFileRotation -XX:+UseParNewGC ",
"heapTuningTips": [
"似乎您过度分配了 Metaspace 的大小。在整个运行过程中,Metaspace 的峰值利用率仅为已分配大小的 4.53%。您可考虑降低 Metaspace 的大小。"
],
"tipsToReduceGCTime": [
{
"issue":"15.34% 的 GC 时间(即 54 分钟 13 秒 710 毫秒)是由 “并发模式失败”引起的。CMS 收集器会使用一个或多个垃圾回收线程,这些线程会与应用程序线程同时运行,目标是在 Tenured 代充满之前完成针对其的垃圾回收工作。在正常过程中,CMS 收集器会在程序线程运行的同时执行大部分追踪和扫描工作,因此程序线程只会出现短暂的暂停情况。但是,如果 CMS 收集器无法在 Tenured 代填满之前完成对象的回收工作,或者 Tenured 代中没有足够的空闲空间块能够用于分配的,则应用程序将被暂停且完成回收工作,同时所有程序线程都会被停止。无法同时完成回收的情形,就被称是为“并发模式失败”,表明需要调整 CMS 收集器参数。并发模式失败通常会触发 Full GC。",
"solution": "并发模式问题可以通过增加 Tenured 代大小来避免,或者通过将‘CMSInitiatingOccupancyFraction’设置为较低的值并将‘UseCMSInitiatingOccupancyOnly’设置为 true,以在较小的堆内存占用率下启动 CMS 回收。CMSInitiatingOccupancyFraction 的选择应当谨慎,将其值设置得过低会导致 CMS 回收过于频繁。"
}
],
"throughputPercentage": 99.996,
"responseId": "8296b5c3-25c7-4157-92df-a54d9083bab7",
"graphs": {
"heapAfterGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_after_gc-aad50e08-951f-4eca-9cc2-e2b296ba3f8b.png",
"heapBeforeGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_before_gc-868d5a56-c8b6-4125-bf8d-dc557937033a.png",
"gcDurationGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_duration-1048abf9-8833-44f1-a990-9a6dd24e9a94.png",
"gcPauseDurationGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_pause_duration-ef8b210e-1d08-4b5f-be28-e2d54a43732d.png"
}
"webReport": "http://gceasy.io/my-gc-report.jsp?p=YXJjaGl2ZWQvMjAxOS8wNC8xNC8tLWFwaS1lMDk0YTM0ZS1jM2ViLTRjOWEtODI1NC1mMGRkMTA3MjQ1Y2M1YjBjMTMzNy0yMDQyLTQ4NzAtYmI5My01NmEwZjUzOTg3M2YudHh0LS0=&channel=API",
"pdfReport": "http://gceasy.io/my-gc-report.jsp?p=YXJjaGl2ZWQvMjAxOS8wNC8xNC8tLWFwaS1lMDk0YTM0ZS1jM2ViLTRjOWEtODI1NC1mMGRkMTA3MjQ1Y2M1YjBjMTMzNy0yMDQyLTQ4NzAtYmI5My01NmEwZjUzOTg3M2YudHh0LS0=&channel=API&isPrinterFriendly=true"
}
JSON 响应元素
元素 | 描述 |
responseId | 为各个响应生成的唯一事务 ID。可用于调试和诊断 |
webReport | 在网页浏览器中查看此 GC 分析可视化网页报告的超链接。 |
pdfReport | 通过网络浏览器下载此 GC 分析 PDF 报告的超链接。 |
isProblem | 如找到任何内存问题则会返回“true”。如未找到内存问题则会返回“false”。此元素可用于主动 GC 监测。 |
problem | 内存问题的描述将通过此元素给出。比如内存问题的类型、内存问题的副作用及其可能导致的表现等等 |
jvmHeapSize | 该部分的数据点是从 GC 日志中收集而来的,因此可能会与 JVM 系统属性(即:–Xmx、-Xms…)指定的大小相匹配,也可能会不匹配。假设您已将总的堆内存大小(即:–Xmx)配置为 2 GB,但在运行时,如果 JVM 只分配了 1 GB,那么在本报告中您将看到已分配的大小仅为 1 GB。 |
youngGen | |
> allocatedSize | Young 代已分配大小(即:在 JVM 水平指定的大小) |
> peakSize | Young 代运行时的峰值利用率大小 |
oldGen | |
> allocatedSize | Old 代已分配大小(即:在 JVM 水平指定的大小) |
> peakSize | Old 代运行时的峰值利用率大小 |
Metaspace | |
> allocatedSize | Metaspace 的已分配大小(即:在 JVM 水平指定的大小) |
> peakSize | Metaspace 的运行时峰值利用率大小 |
permGen | |
> allocatedSize | Perm 代已分配大小(即:在 JVM 水平指定的大小) |
> peakSize | Perm 代运行时的峰值利用率大小 |
total | |
> allocatedSize | 总的已分配堆内存大小(即:在 JVM 水平指定的大小),包含 Young + Old + Perm(或 Metaspace) |
> peakSize | 堆内存运行时的峰值利用率大小 |
gcStatistics | GC 统计数据摘要基于 GC 日志中报告的“real”时间。有关 user、sys、real 时间差别的更多信息,请参考 http://blog.gceasy.io/2016/04/06/gc-logging-user-sys-real-which-time-to-use/ |
> totalCreatedBytes | 应用程序创建的总对象数。 |
> measurementDuration | 应用程序运行的总时间 |
> startTimestamp | 报告首个 GC 事件的时间戳 |
> endTimestamp | 报告最后一个 GC 事件的时间戳 |
> avgAllocationRate | 程序对象创建率。在分配更多对象时,Young 代将会很快填满,Minor GC 的出现频率会提高。 |
> avgPromotionRate | 从 Young 代到 Old 代的对象晋升率。当有更多对象被提升到 Old 代时,Full GC 将更频繁地运行。 |
> minorGCCount | 程序中发生 Minor GC 的次数 |
> minorGCTotalTime | Minor GC 花费的总时间 |
> minorGCAvgTime | Minor GC 所花费的平均时间(即:所有 Minor GC 所花费的总时间/Minor GC 次数) |
> minorGCAvgTimeStdDeviation | Minor GC 平均时间标准差 |
> minorGCMinTIme | 所有 Minor GC 的最小时间 |
> minorGCMaxTime | 所有 Minor GC 的最大时间 |
> minorGCIntervalAvgTime | Minor GC 间的平均时间间隔 |
> fullGCCount | 程序中发生 Full GC 的次数 |
> fullGCTotalTime | Full GC 花费的总时间 |
> fullGCAvgTime | Full GC 所花费的平均时间(即:所有 Full GC 所花费的总时间/Full GC 次数) |
> fullGCAvgTimeStdDeviation | Full GC 平均时间标准差 |
> fullGCMinTime | 所有 Full GC 的最小时间 |
> fullGCMaxTime | 所有 Full GC 的最大时间 |
> fullGCIntervalAvgTime | Full GC 间的平均时间间隔 |
gcKPI | 此 GC 分析的关键性能指标 |
>throughputPercentage | 处理真实事务所花费的时间 vs GC活动所花费的时间(百分比)。百分比数值较高意味着 GC 开销较低。应该以高吞吐量为目标。 |
>averagePauseTime | 平均 GC 停顿时间(毫秒) |
>maxPauseTime | 最大 GC 停顿时间(毫秒) |
gcDurationSummary | |
> groups | GC 持续时间摘要数组。示例组: { “start”: “0.2”, “end”: “0.3”, “numberOfGCs”: 5 }, 表示 5 次 GC 在 0.2 秒至 0.3 秒之间完成 |
>> start | 报告的组开始时间(秒) |
>> end | 报告的组结束时间(秒) |
>> numberOfGCs | “start”时间和“end”时间之间完成的 GC 次数 |
graphs | 此 GC 日志分析的图形图像可以在该子元素中找到 |
> heapAfterGCGraph | 包含指向堆内存使用情况(GC 后)图形图像的 URL |
> heapBeforeGCGraph | 包含指向堆内存使用情况(GC 前)图形图像的 URL |
> gcDurationGraph | 包含指向 GC 持续时间图形图像的 URL |
> gcPauseDurationGCGraph | 包含指向 GC 停顿持续时间图形图像的 URL |
gcCauses | 报告 GC 原因的数组 |
> cause | 触发 GC 的原因。其中的值可能是:并发模式失败、分配失败、System.gc()调用 |
> count | 因此原因而导致的 GC 次数 |
commandLineFlags | 传递给应用程序的 JVM 参数 |
heapTuningTips | 数组。可选元素。提供 JVM 堆内存大小调优的建议 |
tipsToReduceGCTime | 数组。可选元素。提供缩短 GC 时间的建议 |
>issue | 说明引发 GC 的原因 |
>solution | 减少由此原因导致 GC 的解决方案 |
标记报告
假设您需要分析数百 JVM 的 GC 日志。此时可能需要使用主机名、日期等信息来对报告进行标记,这样就能清楚地知道其中的对应关系了。可通过在 GC API 端点中传递请求参数“fileName”来实现这一功能,如:
https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&fileName={YOUR_TAG}
响应 JSON 中包含“webReport”元素。该元素中包含一个 URL。在浏览器中访问该 URL 可看到通过 API 解析的 GC 日志可视化报告。现在,您将可在浏览器报告中的右上角看到通过 API 传递的标签。
比如您在 API 端点中传递了 fileName=hostABC8080,那么报告中就会如实展示。

图:通过 API 传递了标签的 GCeasy 报告
XML 响应
默认情况下 API 响应会以 JSON 格式发送。但是如果您想获取 XML 格式的相应,则可在 HTTP Header 元素中传递“accept”参数,值为“xml”即可。
Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY} –-header "accept:xml"
也可在 URL 参数中使用“accept”元素来调用 API
Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&accept=xml
图形图像
部分客户希望能够在 GCeasy API 响应中包含指向图形图像的 URL。客户会在以下情形中使用这些图形图像:
a.构建 GC 日志分析仪表板。
b.将 GC 分析集成至 CI/CD 管线。
c.横跨数百节点自动生成性能报告。
如需在 API 响应中启用图形,您需要在 API 请求 Header 中传递“graphs=true”,如下所示:
Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&graphs=true
然后您将能看到 API 响应中包含指向图形的 URL:
"graphs": {
"heapAfterGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_after_gc-aad50e08-951f-4eca-9cc2-e2b296ba3f8b.png",
"heapBeforeGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_before_gc-868d5a56-c8b6-4125-bf8d-dc557937033a.png",
"gcDurationGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_duration-1048abf9-8833-44f1-a990-9a6dd24e9a94.png",
"gcPauseDurationGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_pause_duration-ef8b210e-1d08-4b5f-be28-e2d54a43732d.png"
}
统一单位
包含内存大小的响应元素将以 kb、mb、gb、tb 为单位回传。示例:
“allocatedSize”: “2.9 gb”,
“peakSize”: “1.36 gb”
同样的,带有时间的元素将以小时、分钟、秒、毫秒为单位回传。示例:
“minorGCTotalTime”: “1 min 9 sec 408 ms”,
“minorGCMaxTime”: “1 sec 65 ms”, 如果您想以内存单位“bytes”和时间单位“毫秒”来对单位进行统一,则可传递值为“true”的“normalizeUnits”URL 参数
Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&normalizeUnits=true
此时调用包含选项的 API 会返回如下所示的统一单位响应元素:
“allocatedSize”: “3.113877504E9”,
“peakSize”: “2.95285248E9”
“minorGCTotalTime”: “69408.36”,
“minorGCMaxTime”: “1065.17”,
基于时间的过滤
有时您可能会想要对某个时间段内的 GC 日志进行分析,而不是分析整个 Java GC 日志。下面是一些相关情形:
1. 如果 GC 日志未被配置为覆盖的话(这也是大部分组织的通常情况),则单个 GC 日志文件中最终将包含所有 GC 事件的信息。部分程序可能已经启动了好几天甚至好几周。因此,单一个 GC 日志文件中最终将包含这些时间内的所有 GC 事件。但是,用户可能只想对最近 24 小时的 GC 活动进行分析
2. 各个应用程序将在同一天中出现高流量和低流量的时段。用户可能只想分析峰值流量时段的 GC 情况。比如一名来自金融行业用户,他只想在 COW(关键在线窗口期)期间(即:9:00AM – 6:00PM)对 GC 活动进行监测。
如需进行此类基于时间的处理,请参考本文。
相对时间戳转绝对时间戳
在您的 GC 日志文件中,时间戳可能会以相对格式输出,如:
[0.209s] .....
但是如果您想以绝对时间戳在 GCeasy 图表中进行绘制,则可在 API 请求中传递“initialTimestamp”参数。有关此功能的更多详情可在这里查看。
API 响应关键元素
GCeasy 的 JSON API 可用于应用程序监测、CI/CD 管线代码质量分析以及多种其他目的。API 响应中包含丰富的信息集(即:元素)。在本文中,我们着重介绍了 API 响应中的一些关键元素。如果这些元素的值超过或低于特定阈值,你可能就需要考虑给出警报或中断程序。
最佳实践:构建警报
出于生产监测或性能测试目的,您可以围绕 JSON 响应构建警报。
a.如果“isProblem”元素的值为“true”,那么可以使用“problem”元素中的内容来生成警报。
b.您还可在
“fullGCCount”、“fullGCTotalTime”、“fullGCAvgTime”、“fullGCAvgTimeStdDeviation”、“fullGCMinTIme”、“fullGCMaxTime”、“fullGCIntervalAvgTime”等元素上设置阈值。如果任意上述元素值超出您所设置的阈值,则也可以触发警报。
Leave a Reply