5

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

  • 雄猫 7.0
  • JRuby 1.6.7.2 (Ruby-1.9.2-p312)
  • JVM 1.7.0.25
  • 导轨 3.2.7
  • jruby 机架 1.1.7
  • 莺1.3.6

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

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

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

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

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

编辑:

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

问题嫌疑人1

由“org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988”加载的 6.458 个“org.jruby.RubyClass”实例占用 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

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

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

问题嫌疑人4

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

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

4

2 回答 2

2

首先:256M 堆空间对于 Java 应用程序来说并不多——尤其是涉及到一个完整的 servlet 容器/应用程序服务器和(可能)很多库。

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

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

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

于 2013-07-05T12:03:47.627 回答
1

这闻起来很像内存泄漏。不是一个漂亮的景象。

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

我会尝试的另一件事是使用一些工具进行代码检查。

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

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

于 2013-07-01T12:25:30.877 回答