内存泄漏检测
Site24x7 APM 中的内存泄漏检测功能可帮助您在内存泄漏严重影响应用程序性能之前及时发现并加以解决。
什么是内存泄漏?
当应用程序分配了内存资源但在不再需要时未能正确释放,就会发生内存泄漏。这种情况通常是由于不良的编码实践造成的。
当应用程序持续占用内存而不释放时,服务器内存将耗尽。一旦服务器内存被完全占满,应用程序将会崩溃。
在 Java 中,为资源分配的内存通常在垃圾回收时释放。但有时某些资源在垃圾回收过程中被跳过,从而导致应用程序发生内存泄漏。
内存泄漏检测选项卡中的按需内存分析功能可追踪集合,并使用线性回归模型识别潜在泄漏。您可以通过追踪集合中对象随时间的增长来识别泄漏的根本原因。
按需内存分析
通过按需内存分析,您可以快速识别代码堆栈中占用内存最多的类。指定时间内收集到的所有对象将与关联指标一同列出。
按以下步骤启动按需内存分析:
- 登录 Site24x7 Web 客户端。
- 转到 APM > 您的 Java 应用程序。
- 单击 JVM 选项卡,然后单击其下方的内存泄漏检测选项卡。
- 要启动内存分析,请单击启动内存分析按钮。
注意
每个实例每天最多可执行 10 次按需内存分析。

- 修改所列参数以自定义分析。

- 分析持续时间:选择 5 至 30 分钟,作为分析器收集对象的时长。
- 对象存活时间:设置 1 至 9 分钟,作为分析期间捕获对象所需的存活时间。
例如:若对象存活时间设为 5,则在分析启动 5 分钟后仍处于活跃状态的对象将被捕获。注意存活时间的最大值为分析持续时间值的 30%。
例如:若分析持续时间设为 20,则存活时间可选范围为 1 至 6,因为 6 是 20 的 30%。 - 实例:按需内存分析既可针对应用程序,也可针对实例启动。
- 在应用程序视图中,可以选择多个要启动分析的实例。
- 在实例视图中,默认选中该实例,实例下拉菜单处于禁用状态。
- 单击启动以开始内存分析。
启动按需内存分析后,启动内存分析按钮将替换为分析已初始化按钮(该按钮处于禁用状态)。

在以下情况下,启动内存分析按钮将处于禁用状态:
- 监视器状态为宕机或已暂停。
- Java 代理版本低于 5.8。
- 内存泄漏分析当前正在执行。
按需内存分析完成后,捕获的数据将显示在内存泄漏检测选项卡上。捕获的指标提供以下视图:
表格视图
在表格视图中,将显示分析期间收集到的内存对象及其关联指标。
单击某个内存对象时,将跳转至对应的详情视图。

| 参数 | 说明 |
| 类名 | 内存对象所属类的名称。 |
| 元素数量 | 内存对象中存储的元素总数。 |
| 对象泄漏状态 | 对象是否存在内存泄漏:
|
| 对象创建时间 | 对象被捕获的时间。 |
| 实例名称 | 实例的名称。 |
近期内存事件部分显示与所选内存对象关联的每次内存泄漏事件的摘要以及各事件发生的时间,有助于加快故障排除并预防类似内存泄漏问题再次发生。
- 仅列出最近 25 次内存泄漏事件。
- 单击任意内存对象关联的事件摘要时,将跳转至对应的详情视图。
详情视图
在详情视图中,单击左侧面板中列出的各个类,可查看对象的更多详细信息。

| 参数 | 说明 |
| 类名 | 包含内存对象的类的名称。 |
| 元素数量 | 内存对象中存储的元素总数。 |
单击每个类可查看关联指标,指标分为三个选项卡:
概述
顶部区域显示对象的内存泄漏状态、元素数量和对象大小。

元素数量显示元素数量随时间变化的图形,并附有第 95 百分位线。
近期内存事件显示与所选类相关的每次内存事件的摘要及各事件发生的时间。
内容检查
启用内容检查后,代理将监控所选类中对象的大小。若对象大小在用户指定的时间段内每分钟发生变化,代理将捕获数据并每分钟将其显示在 Site24x7 Web 客户端中。因此,您可以在内容检查选项卡上查看每分钟更新的数据。
启动内容检查:
- 从左侧面板选择类,然后单击检查对象内容以打开按需用户操作对话框。
注意
当存在内存泄漏时,代理会自动启用内容检查流程。
- 指定 5 至 30 分钟的检查持续时间。
- 单击启动以开始内容检查。

分析完成后,可查看时间戳和相应指标。

| 参数 | 说明 |
| 时间 | 内存对象被捕获的时间。 |
| 类 | 被捕获的内存对象。 |
| 数量 | 内存对象中存储的元素总数。 |
| 大小 | 内存对象的大小。 |
- 中间面板将显示时间戳(每分钟一个)。单击每个时间戳时,该时间捕获的对象及其指标将显示在右侧面板中。
- 若所选对象(在类名下)的大小未发生变化,则 Site24x7 Web 客户端中将仅显示第一分钟的数据。
访问追踪
启用访问追踪后,代理将在用户指定的时间段内监控所选类中的对象。若通过任何代码路径访问了这些对象,代理将捕获相应代码路径。追踪完成后,捕获的指标将显示在 Site24x7 Web 客户端中。
启动访问追踪:
- 从左侧面板选择类,然后单击捕获对象跟踪以打开按需用户操作对话框。
注意
当存在内存泄漏时,代理会自动启用访问追踪流程。
- 指定 5 至 30 分钟的追踪持续时间。
- 单击启动以开始访问追踪。

追踪完成后,指标将显示在访问追踪选项卡上。
每次会话代理最多只能捕获 25 个对象。
| 参数 | 说明 |
| 时间 | 代码路径被捕获的时间。 |
| 代码路径 | 发现内存对象的追踪路径。 |
| 出现次数 | 相同追踪路径被收集的次数。 |
中间面板将显示对象被捕获时的时间戳列表。单击某个时间戳时,该时间捕获的代码路径将显示在右侧面板中。
- 若同一对象再次通过相同代码路径被访问,将不会新增时间戳,而是出现次数字段中的数字每次加一。
- 若所选对象(在类名下)在指定时间内未被访问,则不会显示任何数据。

使用场景
设想这样一种场景:您的 Java 应用程序由于代码中的逻辑错误,意外地保留了不再需要的对象引用(声明为静态变量)。这些无意保留的对象引用阻止了内置垃圾回收机制释放这些对象占用的内存。集合对象持续增长,在应用程序的整个生命周期内始终驻留在内存中,导致其他关键内存无法被使用。
APM 代理如何判断一个对象是否存在泄漏?
Site24x7 在捕获 Java 集合对象之前,会考量以下条件:
• 用户必须在启动内存泄漏检测时提供对象的存活时间。
• 集合或映射中的元素数量必须超过 1,000。
• 对象大小必须超过 5MB。
Java 代理捕获集合对象,并使用线性回归模型确认潜在泄漏。Site24x7 在集合对象达到长期增长趋势的判定条件后,持续监控其大小。正向增长表明该集合对象是潜在的泄漏对象,也是内存泄漏的根源。
确认对象为潜在泄漏后的下一步
检测到潜在内存泄漏后,您需要通过以下操作进行故障排除:
避免或防止泄漏的最佳实践
• 在不必要的地方避免将集合对象声明为静态变量。
• 选择合适的集合或映射类型。
• 使用菱形运算符和泛型类型。
