
本文介绍如何使用 Map 结构,结合 LinkedHashMap 和 computeIfAbsent,按原始行序(即索引位置)逐条比对两组 /proc/[pid]/maps 风格输出中相同文件名对应的内存地址是否一致。
本文介绍如何使用 map
在分析进程内存映射(如 Linux 的 /proc/[pid]/maps)时,常需判断多次采样中同一索引位置的映射段是否发生地址偏移——例如第 1 行的 libm-2.31.so 映射起始地址是否变化。直接用 HashMap
以下为完整实现方案:
✅ 核心设计:带索引的键名 + 有序列表存储
public static Map<string list>> getMemoryAddressWithFileName(String[] responses) {
Map<string list>> map = new LinkedHashMap(); // 保持插入顺序
for (String response : responses) {
Scanner s = new Scanner(response);
int keyIndex = 1;
while (s.hasNextLine()) {
String line = s.nextLine().trim();
if (line.isEmpty()) continue;
// 使用正向先行断言分割:空格后紧跟 '/' 的位置(避免误切路径中的空格)
String[] parts = line.split("\s+(?=/)", 2);
if (parts.length new ArrayList()).add(address);
}
s.close();
}
return map;
}</string></string>
✅ 使用示例:比对并输出稳定性结论
String output1 = "b3e74000-b3ec5000 r-xp 00000000 fb:00 1653 /lib/libm-2.31.so
" +
"b3ec5000-b3ed4000 ---p 00051000 fb:00 1653 /lib/libm-2.31.so
" +
"b3ee7000-b3ee8000 r--p 00050000 fb:00 1653 /lib/libm-2.31.so
" +
"b3ed5000-b3ed6000 rw-p 00051000 fb:00 1653 /lib/libm-2.31.so";
String output2 = "
" +
"b3e74000-b3ec5000 r-xp 00000000 fb:00 1653 /lib/libm-2.31.so
" +
"b3ed8000-b3ee7000 ---p 00051000 fb:00 1653 /lib/libm-2.31.so
" +
"b3ee7000-b3ee8000 r--p 00050000 fb:00 1653 /lib/libm-2.31.so
" +
"b3ee8000-b3ee9000 rw-p 00051000 fb:00 1653 /lib/libm-2.31.so";
Map<string list>> result = getMemoryAddressWithFileName(new String[]{output1, output2});
for (Map.Entry<string list>> entry : result.entrySet()) {
List<string> addresses = entry.getValue();
if (addresses.size() == 2) {
String addr1 = addresses.get(0);
String addr2 = addresses.get(1);
boolean unchanged = addr1.equals(addr2);
System.out.printf("Segment %s: '%s' → '%s' → %s%n",
entry.getKey(), addr1, addr2, unchanged ? "STABLE" : "CHANGED");
}
}</string></string></string>
输出结果:
Segment /lib/libm-2.31.so#1: 'b3e74000-b3ec5000' → 'b3e74000-b3ec5000' → STABLE Segment /lib/libm-2.31.so#2: 'b3ec5000-b3ed4000' → 'b3ed8000-b3ee7000' → CHANGED Segment /lib/libm-2.31.so#3: 'b3ee7000-b3ee8000' → 'b3ee7000-b3ee8000' → STABLE Segment /lib/libm-2.31.so#4: 'b3ed5000-b3ed6000' → 'b3ee8000-b3ee9000' → CHANGED
⚠️ 关键注意事项
- 必须使用 LinkedHashMap:保证 entrySet() 迭代顺序与输入行序一致,否则索引对齐失效;
- 键构造不可仅依赖文件名:同一 .so 文件可能在单次映射中出现多次(如代码段、数据段、重定位段),需附加 #n 索引;
- 解析需鲁棒:使用 \s+(?=/) 正则分割,精准定位文件路径起始位置,避免因路径含空格(如 /usr/lib/x86_64-linux-gnu/libstdc++.so.6)导致解析错误;
- 空行/脏数据过滤:trim() + isEmpty() 判定,防止 或空白行干扰索引计数;
- 内存地址提取要严谨:取首字段后再按空格切分,确保获取的是 addr-addr 字符串,而非权限字段。
该方案彻底规避了传统 HashMap 键冲突与顺序丢失问题,真正实现了“同位置、同文件、同语义”的精准比对,适用于 ASLR 分析、内存布局审计及安全加固验证等场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











