Java内存之谜(我有泄漏)?

时间:2009-09-25 03:33:55

标签: java linux optimization memory heap

我在linux服务器上运行一个独立的Java问题。我用-Xmx256m启动了jvm。我附加了一个JMX监视器,可以看到堆永远不会真正通过256Mb。但是,在我的linux系统上运行top命令时,我可以看到:

1)首先,此进程的RES内存使用量约为350Mb。为什么?我想这是因为堆外的内存?

2)其次,这个过程的VIRT内存使用量不断增长和增长。它永远不会停止!它现在显示在2500Mb!我有泄漏吗?但堆不会增加,它只是循环!

最终这会带来一个问题,因为系统的交换不断增长,最终导致系统死亡。

任何想法发生了什么?


我想问的一个重要问题,这可能是我的代码而不是JVM,kernal等的一些情况。例如,如果线程数量不断增长,那么这是否合适我的观察描述?您可以建议我注意哪些类似的东西?

6 个答案:

答案 0 :(得分:9)

一些潜在的问题:

  • 直接分配的缓冲区和内存映射文件在Java堆外部分配,无法方便地进行处理。
  • 为每个新线程保留堆栈区域。
  • 永久生成(代码和实习字符串)超出了通常的堆栈。这可能是类加载器泄漏的问题(通常在重新加载webapps时)。
  • C堆可能正在泄漏。

pmap -x应该显示你的记忆是如何消失的。

答案 1 :(得分:1)

Swap Sun与IBM JVM进行测试


  1. RES将包含代码+非头数据。此外,您认为存储在堆中的某些内容不是,例如线程堆栈和“类数据”。 (这是一个定义问题,但代码和类数据由-XX:MaxPermSize=控制。)

  2. 这听起来像是JVM实现,Linux内核或库JNI代码中的内存泄漏。

  3. 如果使用Sun JVM,请尝试使用IBM,反之亦然。

    我不确定dlopen是如何工作的,但是如果可能的话,访问系统库的代码可能会重复重新映射相同的东西。

    最后,您应该使用ulimit提前使系统失败,这样您就可以轻松地重复测试。

答案 2 :(得分:1)

WRT#1,你的RSS大于你的堆是正常的。这是因为system libraries and non-Java code are included in the RSS but not the heap size

WRT#2,是的,听起来你有某种泄漏。如果系统本身崩溃,您可能会消耗太多的系统资源,如套接字,线程或文件。

尝试使用lsof查看JVM已打开的文件。随着记忆力的增加,运行几次。如果JVM崩溃,请务必设置-XX:+HeapDumpOnOutOfMemoryError选项。

答案 3 :(得分:1)

根据我的经验,Java中非堆内存泄漏的最常见原因是线程泄漏

您可能会觉得有用的工具是 jvmtop ,它可以让您实时监控堆大小,线程数和其他指标。

答案 4 :(得分:0)

听起来你有泄漏。你能不能分析哪个功能正在推动内存?我不确定。

答案 5 :(得分:0)

如果我不得不在黑暗中捅,我会说你正在使用的JVM有内存泄漏。