Java进程的内存使用量比Runtime.totalMemory方法等所显示的要多得多。

3

我已经陷入这个问题很长时间了,没有任何线索。如果有人能帮忙,将不胜感激。

我在ARM v7处理器的设备上运行Java应用程序。它安装了Ubuntu。当使用“top”或“free -m”命令查看进程的内存使用情况时,其使用量约为180 MB,这比Runtime.freeMemory等方法告诉我的要多得多。

这是我启动应用程序的方式:

java -Xcheck:jni -XX:MaxPermSize=25m -Xmx65m -XX:ReservedCodeCacheSize=10m -jar MyAPP.jar myconfig.xml

就我所知,该进程的总内存使用量不应超过25 + 65 + 10 = 100 MB。可能会多一些(我不知道的其他非堆空间)。但即使如此,我认为差异也不应该这么大(80 MB)。

这是Runtime命令在我的日志中给我展示的信息(我将这些命令用于打印调试日志的一部分)。

使用信息:可用处理器:2 可供JVM使用的可用内存:8474344,当前内存使用情况:5943576,JVM允许使用的最大内存:66977792

来自“top”的输出:

PID   USER     PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
3926  linaro   20  0   266m  188m 3636 S  1.0 21.1   0:37.81 java

“free -m” 的输出结果:

当 Java 进程正在运行时:

        total       used       free     shared    buffers     cached
Mem:     893         842         51          0         40        216
-/+ buffers/cache:   585        308
Swap:     0          0          0

当进程已停止时:
         total      used       free     shared    buffers     cached
Mem:      893        656        237          0         40        216
-/+ buffers/cache:   400        493
Swap:      0          0          0

正如我们所看到的,493-308=185,与“top”有关于该进程内存使用情况的说法相匹配(早些时候我认为可能是安装在这台机器上的 top 存在 bug)。
我也对该进程进行了远程监控,它显示约 14M 的“committed”堆空间和约 20M 的非堆空间。至少堆空间与我从“Runtime”命令中获得的一致。因此,即使远程监控工具似乎表明内存使用情况远低于180M。
最奇怪的部分是,当我在我的笔记本电脑(MacBook Pro)或标准的基于英特尔的 Linux 盒子(非 ARM)上运行同一个 jar 文件时,一切都正常。进程只使用大约60MB的空间,这也是我所期望的。
另一个值得一提的点是,我在ARM设备上使用的Java VM是Oracle的Java SE嵌入式版本。
有没有人对内存使用方面的差异有什么想法?很抱歉问了这么长的问题 :-)
更新:
在对 Java 进程的各个部分消耗内存进行了一些研究后,我将注意力集中在本地代码交互(JNI)上。这是唯一一个我们无法通过命令行参数限制其内存消耗的家伙。在我的程序中,我使用 sqlite-jdbc 驱动程序访问数据库。我注释了数据库访问部分,内存使用量降至24MB!!!
因此,我猜测这种内存差异与 sqlite jdbc 访问有关,尽管还不确定是什么原因。随着我取得进展,我会继续更新。
-Sandeep
1个回答

1

我知道堆空间完全在限制范围内。但是进程内存我无法确定它花费在哪里。我正在寻找一种方法来找出谁在使用进程内存的哪个部分。我也查看了我的进程的/proc/id/smaps输出。似乎有大约140MB的内存被匿名映射,即没有实际文件与该内存映射。有没有办法找出谁负责匿名内存分配? - schauhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接