先获取事实,不要先猜测泄漏,不要通过清理工作集改变现场。
import process.memoryMap;
var mm = process.memoryMap;
var report,err = mm.diagnose(,{
requestBytes = 128 * 1048576;
resolveNames = true;
top = 5;
});
if(!report) return {error=err};
return {text=mm.format(report); request=report.request; findings=report.findings};
顺序:
target.pid 和 collectorPid。complete、stopReason、scanRange.fullAddressSpace。request.status;未发现时再区分总量不足、碎片和对齐限制。counters 分开理解。候选存在仍可能因系统提交限额、配额、堆内部机制等原因分配失败。下面两个脚本用于独立采集进程,启动参数 --pid=目标PID 必须明确指定。样例路径位于采集程序的应用目录下。
操作前:
import process.memoryMap;
import JSON;
var pid = tonumber(_ARGV.pid);
if(!pid) return {error="请指定 --pid=目标PID,不能省略目标。"};
var before,err = process.memoryMap.snapshot(pid);
if(!before) return {error=err};
if(!before.complete) return {error="扫描不完整"; detail=before.stopReason};
var ok = JSON.save("/memory-diagnostics/before.json",before,true);
return {saved=ok; target=before.target};
完成需要观察的操作后:
import process.memoryMap;
import JSON;
var mm = process.memoryMap;
var pid = tonumber(_ARGV.pid);
if(!pid) return {error="请指定 --pid=目标PID。"};
var before,err = JSON.load("/memory-diagnostics/before.json");
if(!before) return {error=err};
var after,err = mm.snapshot(pid);
if(!after) return {error=err};
var delta,err = mm.diff(before,after,{top=10});
if(!delta) return {error=err};
JSON.save("/memory-diagnostics/after.json",after,true);
JSON.save("/memory-diagnostics/diff.json",delta,true);
return {text=mm.format(delta); delta=delta.delta};
加载器、线程池、缓存和运行库可能延迟释放资源。要排查增长,建议观察:基线 → 操作一次 → 释放 → 重复多次 → 等待稳定。持续增长是线索,不是泄漏证明。
若必须在目标内采集,第二次快照会包含第一份快照仍驻留所造成的影响。库会提示 SELF_OBSERVATION;不要把快照对象自身误认为业务泄漏。
import process.memoryMap;
import JSON;
var saved,err = JSON.load("/memory-diagnostics/before.json");
if(!saved) return {error=err};
var report,err = process.memoryMap.analyze(saved,{
requestBytes = 64 * 1048576;
top = 8;
});
if(!report) return {error=err};
return process.memoryMap.format(report);
更改分析选项不重新扫描目标,因此可用同一份快照分别评估 64 MiB、128 MiB 等请求。
import process.memoryMap;
var pid = tonumber(_ARGV.pid);
var address = tonumber(_ARGV.address);
if(!pid || address===null) return {error="请提供 --pid 和 --address。"};
var info,err = process.memoryMap.query(pid,address,{resolveNames=true});
if(!info) return {error=err};
return {text=process.memoryMap.format(info); detail=info};
这里不解引用地址,不触发 PAGE_GUARD。查询结果也不保证之后能安全读取该地址。
diagnose(),诊断的就是这个新进程。GetCurrentProcessId(),再将该 PID 显式传给子进程。return,必须显式写入文件或通过 IPC 回传;不要假设工具会自动回传报告。appBaseDirectory="/",让代码内的 /文件 与工具读取的工作区 /文件 对应。可在子进程运行的采集脚本(启动时传 --pid、--output):
import process.memoryMap;
import JSON;
var pid = tonumber(_ARGV.pid);
var output = _ARGV.output;
if(!pid || !#output) return;
var report,err = process.memoryMap.diagnose(pid,{top=5});
JSON.save(output,{report=report; error=err},true);
报告包含实际 target.pid,接收端仍应核对目标与创建时间,不能只根据文件名推测诊断对象。
可把下列短描述加入自己的库清单或工具知识索引;不需要修改基础 process:
process.memoryMap:进程内存诊断。排查内存不足、连续分配失败、虚拟地址空间碎片、保留区过大及内存增长;支持当前/指定 x86 进程、LAA 高地址、保护页分配、快照对比。首先查询库参考,再用 diagnose;保存现场用 snapshot。只查询元信息,不读写内存内容。
不需要安装多个含义相近的别名库,也不要依赖某个固定进程 PID 或某次扫描的统计值。