为什么我的Tomcat JRuby应用程序中永远不会释放内存?

时间:2013-06-26 07:34:48

标签: java ruby-on-rails tomcat jruby jrubyonrails

我有一个在Tomcat(Warble)中运行的JRuby on Rails应用程序。它使用Java桥连接到Progress(OpenEdge)应用程序服务器......当我监视内存时,它只会继续运行。

  • Tomcat 7.0
  • JRuby 1.6.7.2(Ruby-1.9.2-p312)
  • JVM 1.7.0.25
  • Rails 3.2.7
  • jruby-rack 1.1.7
  • warbler 1.3.6

在这里找到问题的最佳方法是什么?我想它可能是未清理的JRuby对象,或Java桥或垃圾收集器中没有完成其工作的东西......

即使我让这个过程运行了半个小时,内存也不会下降......

  • 有没有办法知道哪些物体还活着?
  • 是否有易于使用的免费工具,通过这些工具,我可以获得有关谁正在使用所有内存的更多信息?

顺便说一句,我已经将Tomcat服务器配置为使用更多内存,但这只是延迟堆空间错误......

编辑:我实际看到的是Tomcat只使用它可以最大限度使用的所有内存(最大内存池)。它永远不会释放它。也许这只是正常的行为...我现在最多设置为256MB,在任务管理器中,内存大约保持在256MB左右。

编辑:

当创建堆转储并让eclipse使用Eclipse Memory Analyzer分析它时,这就是我得到的报告。我认为这是正常的,因为该工具可能并不期望整个JRuby故事......

问题疑似1

6.458“org.jruby.RubyClass”实例,由“org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988”加载,占用56.969.616(31,78%)个字节。

关键字 org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988 org.jruby.RubyClass

问题疑似2

由“org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988”加载的“org.jruby.internal.runtime.methods.DefaultMethod”的10.597个实例占用22.182.112(12,37%)个字节。

关键字 org.jruby.internal.runtime.methods.DefaultMethod org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988

问题可疑3

3.144“org.jruby.RubyModule”实例,由“org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988”加载,占用21.226.816(11,84%)个字节。

关键字 org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988 org.jruby.RubyModule

问题可疑4

<88>“org.jruby.MetaClass”的8.888个实例,由“org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988”加载,占用18.563.784(10,35%)个字节。

关键字 org.jruby.MetaClass org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988

2 个答案:

答案 0 :(得分:1)

这闻起来很像内存泄漏。不是很好看。

如果没有大量代码,请首先检查您是否正在关闭连接和流以及具有方法close的所有对象。如果这是最近出现的问题,请查看上次修改的代码。

我尝试的其他方法是使用some tool进行代码检查。

也许写一些测试来加速泄漏(比如生成请求),然后你可以尝试从应用程序中排除代码,直到找到导致泄漏的区域。

我不建议您检查内存中的对象,因为这是一个缓慢而痛苦的过程。

答案 1 :(得分:1)

首先:对于Java应用程序来说,256M堆空间并不是很多 - 特别是当涉及到一个完整的servlet容器/应用服务器时(可能)有很多库。

Java通常不会将内存交还给操作系统 - 一旦分配,内存将被视为归JVM所有。我相信可能会有一些内存管理实现回传内存,但我从未见过它们。我在生产环境中的典型建议是-Xmx等于-Xms(分配你希望JVM能够立即分配的所有内存)

用尽堆空间是两个(或多个)条件之一的信号:a)您的应用程序存在内存泄漏,b)您没有为应用程序需求分配足够的内容。

为您的JVM提高内存分配并监视内存使用和垃圾收集以排除b) - 如果您可以安全地说您的应用程序有足够的内存满足其需求,请寻找a)并找到内存的根本原因泄漏。你最好使用一个分析器,但是有256M的内存,很有可能你的内存不足。