Category Total Private Shareable Shared
Pages KBytes KBytes KBytes KBytes
Page Table Pages 20 80 80 0 0
Other System 10 40 40 0 0
Code/StaticData 1539 6156 3988 1200 968
Heap 732 2928 2928 0 0
Stack 9 36 36 0 0
Teb 5 20 20 0 0
Mapped Data 30 120 0 0 120
Other Data 1314 5256 5252 4 0
Total Modules 1539 6156 3988 1200 968
Total Dynamic Data 2090 8360 8236 4 120
Total System 30 120 120 0 0
Grand Total Working Set 3659 14636 12344 1204 1088
最有趣的两个值通常是 Heap (即 Windows 进程堆)和 Other Data。直接通过调用 Windows API 分配的内存组成了进程堆部分,Other Data 中包括 Java 堆。Grand Total Working Set 对应 Task Manager 的 Mem Usage 和 TEB 字段(进程的线程环境块所需要的内存,TEB 是一种 Windows 内部结构)。
最后,在 VADump -o 输出的最下端总结了 DLL、堆和线程栈对工作集的相对贡献:
Module Working Set Contributions in pages
Total Private Shareable Shared Module
9 2 7 0 java.exe
85 5 0 80 ntdll.dll
43 2 0 41 kernel32.dll
15 2 0 13 ADVAPI32.dll
11 2 0 9 RPCRT4.dll
53 6 0 47 MSVCRT.dll
253 31 222 0 jvm.dll
6 3 3 0 jsig.dll
7 4 3 0 xhpi.dll
15 12 3 0 hpi.dll
12 2 0 10 WINMM.dll
21 2 0 19 USER32.dll
14 2 0 12 GDI32.dll
6 2 0 4 LPK.DLL
10 3 0 7 USP10.dll
24 18 6 0 java.dll
22 16 6 0 core.dll
18 14 4 0 zip.dll
915 869 46 0 jitc.dll
Heap Working Set Contributions
6 pages from Process Heap (class 0x00000000)
0x00090000 - 0x00190000 6 pages
2 pages from Private Heap 0 (class 0x00001000)
0x00190000 - 0x001A0000 2 pages
0 pages from UNKNOWN Heap 1 (class 0x00008000)
0x001A0000 - 0x001B0000 0 pages
1 pages from Process Heap (class 0x00000000)
0x00380000 - 0x00390000 1 pages
715 pages from Private Heap 2 (class 0x00001000)
0x00030000 - 0x00040000 15 pages
0x008A0000 - 0x009A0000 241 pages
0x04A60000 - 0x04C60000 450 pages
0x054E0000 - 0x058E0000 9 pages
1 pages from Private Heap 3 (class 0x00001000)
0x00390000 - 0x003A0000 1 pages
7 pages from Private Heap 4 (class 0x00001000)
0x051A0000 - 0x051B0000 7 pages
Stack Working Set Contributions
4 pages from stack for thread 00000F64
1 pages from stack for thread 00000F68
1 pages from stack for thread 00000F78
1 pages from stack for thread 00000F7C
2 pages from stack for thread 00000EB0
通过这种模式还可以用 VADump 获得两个或更多 Java 进程的总和内存占用情况(请参阅本文后面的 技巧和窍门)。
Sysinternals Process Explorer
更有用的内存分析工具来自 Sysinternals 公司(请参阅 参考资料)。其中一个工具是图形化的进程管理器,如图 11 所示,它可以作为 Task Manager 的高级代替品。
图 11. Process Explorer 进程树
Process Explorer 具有和 Task Manager 相同的功能。比方说,您可以得到整个系统性能的动态图形(通过 View --> System Information...),也可用类似的方式配置主进程视图中的列。在 Process --> Properties... 中,Process Explorer 提供了进程的更多信息,比如完整路径和命令行、线程、CPU 实用的动态图表和私有内存。它的用户界面非常好,如图 11 所示。它还可以观察 DLL 的信息和进程的句柄。您可以使用 Options --> Replace Task Manager 用 Process Explorer 代替默认的 Task Manager。
Sysinternals ListDLLs
还可以从 Sysinternals 下载两个命令行工具:ListDLLs 和 Handle。如果希望在脚本或者程序中集成某种形式的内存监控,这两个工具非常有用。
ListDLLs 用于观察 DLL,DLL 可能造成很多内存占用。使用之前请将其添加到路径中,并使用帮助选项获得用法说明。您可以用进程 ID 或进程名调用它。下面是我们的 Java 程序调用 DLL 的列表:
>listdlls -r 3904
ListDLLs V2.23 - DLL lister for Win9x/NT
Copyright (C) 1997-2000 Mark Russinovich
http://www.sysinternals.com
---------------------------------------------------------------------
java.exe pid: 3904
Command line: java -mx1000m -verbosegc Hello
Base Size Version Path
0x00400000 0x9000 141.2003.0005.0022 C:/WINDOWS/system32/java.exe
0x77f50000 0xa7000 5.01.2600.1217 C:/WINDOWS/System32/ntdll.dll
0x77e60000 0xe6000 5.01.2600.1106 C:/WINDOWS/system32/kernel32.dll
0x77dd0000 0x8d000 5.01.2600.1106 C:/WINDOWS/system32/ADVAPI32.dll
0x78000000 0x87000 5.01.2600.1361 C:/WINDOWS/system32/RPCRT4.dll
0x77c10000 0x53000 7.00.2600.1106 C:/WINDOWS/system32/MSVCRT.dll
0x10000000 0x178000 141.2004.0003.0001 C:/Java141/jre/bin/jvm.dll
### Relocated from base of 0x10000000:
0x00280000 0x6000 141.2004.0003.0001 C:/Java141/jre/bin/jsig.dll
### Relocated from base of 0x10000000:
0x00290000 0x7000 141.2004.0003.0001 C:/Java141/jre/bin/xhpi.dll
### Relocated from base of 0x10000000:
0x002a0000 0xf000 141.2004.0003.0001 C:/Java141/jre/bin/hpi.dll
0x76b40000 0x2c000 5.01.2600.1106 C:/WINDOWS/system32/WINMM.dll
0x77d40000 0x8c000 5.01.2600.1255 C:/WINDOWS/system32/USER32.dll
0x7e090000 0x41000 5.01.2600.1346 C:/WINDOWS/system32/GDI32.dll
0x629c0000 0x8000 5.01.2600.1126 C:/WINDOWS/system32/LPK.DLL
0x72fa0000 0x5a000 1.409.2600.1106 C:/WINDOWS/system32/USP10.dll
### Relocated from base of 0x10000000:
0x003c0000 0x18000 141.2004.0003.0001 C:/Java141/jre/bin/java.dll
### Relocated from base of 0x10000000:
0x003e0000 0x17000 141.2004.0003.0001 C:/Java141/jre/bin/core.dll
### Relocated from base of 0x10000000:
0x04a40000 0x12000 141.2004.0003.0001 C:/Java141/jre/bin/zip.dll
### Relocated from base of 0x10000000:
0x04df0000 0x3a1000 141.2004.0003.0001 C:/Java141/jre/bin/jitc.dll
技巧和窍门
现在您已经操作(不是双关语,handle 还有一个含义是句柄)了我们要介绍的所有工具,下面是您单独或一起使用这些工具,改进内存监控的一些方法。
寻找进程 ID
为了找到应用程序的进程 ID,以便在 VADump 这样的命令行工具中使用,请在 Task Manager 中打开 Applications 选项卡右击所关心的进程。选择 Go To Process,这样就会在 Processes 选项卡中看到对应的 ID。
确定一个 Java 进程
是否对那些都命名为 Java 或 javaw 的进程感到困惑,希望找出您要分析的那个进程?如果从 IDE 或脚本中启动 Java 进程,要确定使用了哪一个 JVM 和发送给 Java 进程的命令行参数可能很困难。这些信息可以在 TopToBottom Startup 选项卡中找到。您可以看到调用 JVM 使用的完整命令行和进程启动的时间。
确定大量占用句柄的进程
是否遇到过保存文件却得到提示说文件正被另一个进程使用的情况?或者尝试关闭您认为可靠的程序而得到错误消息的情况?您可以使用 SysInternals Process Explorer 工具的 Handle Search 功能发现谁在捣乱。只要打开 Search 对话框并输入文件名即可。ProcExp 将遍历所有打开的句柄,并确定相应的进程。最终常常会发现,关闭用户界面后,编辑器或者 Web 浏览器还留下一个小的存根进程在运行。
调查有多少内存被共享
您可以使用 VADump 的 -o 选项获得进程当前工作集的详细视图,以及有多少是共享的。获得一个 Java 程序在系统上运行的内存转储,然后再启动另一个并转储。只要比较每个结果的 Code/StaticData 部分,就会发现“Shareable”字节变成了“Shared”,从而稍微降低了内存占用的增加。
清理驻留集
Windows 实现了一种“清除”进程驻留集的策略,在其看起来不再有用的时候予以清除。为了说明这一点,打开 Task Manager 的 Processes 选项框,便可以看到要监控的应用程序进程,然后最小化应用程序窗口,看看 Mem Usage 字段发生了什么变化!
确定应用程序需要的最少内存
对于 Windows Server 2003 和 Windows NT,Microsoft 提供了一个有趣的称为 ClearMem 的工具,如果希望进一步研究 Windows 下应用程序使用内存的情况,它可能非常有用(请参阅 参考资料)。该工具确定了实际内存的大小,分配足够的内存,很快地占用分配的内存然后将其释放。这样就增加了其他应用程序的内存占用压力,反复运行 ClearMem 的结果是迫使应用程序占用的内存数量减少到最小。
结束语
本文简要介绍了 Windows 如何管理内存,考察了一些最有用的免费工具,您可以用这些工具监控 Java 应用程序的内存使用。无疑您还会发现和使用其他的工具,无论从 Web 上免费下载产品还是购买商业产品,我们都希望澄清相互矛盾的术语会对您有所帮助。通常要确定您测量的目标的惟一方法就是做试验,比如我们用于示范 Task Manager 的 VM Size(虚拟内存大小)和 Mem Usage(内存使用)含义的 C 程序。
当然这些工具只能帮助确定问题的所在,如何解决还要靠您自己。多数时候您会发现 Java 堆获取了内存的一大部分,您需要深入分析代码,确定对象引用是否超出了必要的时间。这方面有更多的工具和文章可以提供帮助, 参考资料部分给出了一些有用的链接,可以为您指出正确的方向。
下载
描述
名字
大小
下载方法
A C program to demonstrate how Windows uses memory
experiment.c
3KB HTTP
“ Sensible sanitation -- Understanding the IBM Java Garbage Collector, Part 3”(developerWorks,2002 年 9 月)描述了 JVM 堆参数和 verbosegc 选项。
JInsight 是来自 IBM alphaWorks 的一种 Java 性能工具。
从 developerWorks Java 技术专区中,可以找到数百篇 Java 技术资源。
作者简介
Emma Shepherd 于 2002 年 Warwick 大学获得计算机科学学士学位,毕业后就加入了 IBM。她的上一个项目是关于 Java Web 服务的,她还参与了 IBM WebSphere SDK for Web Services 和 Eclipse 插件的开发。业余时间她喜欢弹钢琴,学说塞尔维亚语。