句柄泄漏是什么
进程每打开一个文件、注册表键、事件、套接字都会占用一个内核句柄,句柄数只涨不落,最终会撞上上限或耗尽非分页内存池。典型表现是服务运行几天后开始报错、无法打开文件,重启一次就好。排查分两步:先用 Handles 属性按进程排序找出嫌疑对象,再用 Sysinternals 的 handle 工具看它到底堆在哪一类对象上。
基本信息
| 适用平台 | Windows 全版本;handle.exe 需从 Sysinternals 获取 |
|---|---|
| 快速排行 | Get-Process | Sort-Object Handles -Descending |
| 下钻工具 | handle.exe、Process Explorer、Performance Monitor |
| 计数来源 | Performance 计数器 Process\Handle Count |
| 观察要求 | 数小时到数天的趋势,单次快照不足以判定 |
| 注意盲区 | GDI/USER 对象不计入 Handles |
典型使用场景
- 服务运行数天后功能异常,怀疑资源泄漏
- 排查“无法打开文件/端口被占用”是否因句柄未释放
- 上线前压测期间观察句柄增长趋势,验证代码有无泄漏
- 对比重启前后同一进程的句柄数,量化泄漏程度
- 定位大量文件句柄指向同一路径,判断是否忘记关闭
常用示例
常用示例
Get-Process | Sort-Object Handles -Descending | Select-Object -First 10 Name, Id, Handles
(Get-Process -Id 1234).Handles # 单进程当前句柄数
Get-Counter "\Process(MySvc)\Handle Count" -SampleInterval 60 -MaxSamples 5 # 观察趋势
handle.exe -p 1234 -s # 按类型统计句柄数
handle.exe -p 1234 -a File # 只看文件类句柄
handle.exe -p 1234 -a File | Select-String 'D:\\Logs' # 找是否堆在同一目录观察指标读法
| 指标 | 正常表现 | 异常含义 |
|---|---|---|
| Handle Count | 随业务负载起落 | 只涨不落即泄漏 |
| 类型分布 | 以 File/Key 为主 | 某类型集中暴增指向具体资源 |
| 同一路径重复 | 少量重复 | 大量同路径句柄=文件未关闭 |
| 增长速率 | 缓慢波动 | 线性增长可推算耗尽时间 |
| GDI/USER | 不计入 Handles | 界面绘制类问题需另查 |
句柄泄漏往往要以小时或天为单位观察才看得出来,采样一次得到的数字只能说明“此刻有多少”,不能证明“在涨”。先建立基线,再按固定间隔采样。
handle.exe 首次运行需要接受许可协议,自动化脚本里加 -accepteula;生产环境只做只读查询,handle.exe 支持关闭句柄但误关会直接导致进程异常。