在Tomcat中跟踪JRuby on Rails的PermGen问题

org*_*gie 5 tomcat memory-leaks jruby jrubyonrails permgen

我们正在运行一个在Tomcat上运行的Rails上写的JRuby的小型Web应用程序.我们正在使用与另一个生产Web应用程序共享的Spring后端.不幸的是,我们一直遇到PermGen问题.

操作系统:Ubuntu Linux 2.6.24-24-server#1 SMP x86_64 GNU/Linux Java:1.6.0_21 Tomcat:6.0.28 JRuby:1.5.0 Rails:2.3.7

我们目前正在被谷歌,雅虎和百度抓获,因此网站使用率上升.我一直在使用JConsole监视Tomcat,我们肯定会看到有太多类的问题.当tomcat启动时,我们加载了大约12,000个类.8小时后,我们加载了近75,000个班级.PermGen同时从100MB增加到460MB.

类卸载工作正常,但它只在同一个8小时内卸载了~500个类.PermGen似乎永远不会被收集.

我们正在运行Tomcat的以下VM选项:

-Xms2048m -Xmx2048m -XX:MaxPermSize=512m -XX:PermSize=128m \
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 \
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
Run Code Online (Sandbox Code Playgroud)

显然存在某种泄漏.问题是在哪里?关于如何追踪谁以及对此负责的任何建议?我希望这是我们的一些非常愚蠢的错误,但我不知道从哪里开始.

任何建议将不胜感激.

编辑

看起来我们正在看到为每个传入请求创建一个新类.

编辑2

这肯定与JRuby有关.使用JConsole,我为类加载器启用了详细模式.以下是来自catalina.out的示例:

[Loaded anon_class1275113147_895127379 from file:/opt/apache-tomcat-6.0.28/webapps/notes/WEB-INF/lib/jruby-core-1.5.0.jar]
[Loaded anon_class1354333392_895127376 from file:/opt/apache-tomcat-6.0.28/webapps/notes/WEB-INF/lib/jruby-core-1.5.0.jar]
[Loaded anon_class1402528430_895127373 from file:/opt/apache-tomcat-6.0.28/webapps/notes/WEB-INF/lib/jruby-core-1.5.0.jar]
Run Code Online (Sandbox Code Playgroud)

那么问题就变成了如何追踪负责创建这些额外课程的一方?

编辑3

不确定这是否是问题所在,但不知何故,我们最终会遇到疯狂的类加载器.跑jmap -permstat PID了但得到了:

class_loader  classes bytes       parent_loader   alive?              type
total = 1320  135748  947431296   N/A             alive=1, dead=1319  N/A
Run Code Online (Sandbox Code Playgroud)

这看起来有点过分了.大多数有三种类型的类加载器的一个:sun.reflect.DelegatingClassLoader,org.jruby.util.JRubyClassLoaderorg.jruby.util.ClassCache$OneShotClassLoader.再次,样本输出来自jmap -permstat:

class_loader            classes bytes      parent_loader           alive?  type
0x00007f71f4e93d58      1       3128       0x00007f71f4d54680      dead    sun/reflect/DelegatingClassLoader@0x00007f72ef9a6dc0
0x00007f721e51e2a0      57103   316038936  0x00007f720431c958      dead    org/jruby/util/JRubyClassLoader@0x00007f72f2fd1158
0x00007f72182f2b10      4       12944      0x00007f721d7f3030      dead    org/jruby/util/JRubyClassLoader@0x00007f72f2fd1158
0x00007f721d7d50d8      9       457520     0x00007f720431c958      dead    org/jruby/util/ClassCache$OneShotClassLoader@0x00007f72f3ce2368
Run Code Online (Sandbox Code Playgroud)

Nic*_*ger 6

PermGen肯定是基于JRuby的应用程序的问题.CMS并没有收集太多内容我并不感到惊讶.通常情况下,没有真正的内存泄漏,而是应用程序对于permgen来说只是沉重而且难以应对.

我可以提供一些选择:

  1. 进一步提高permgen,看看你是否能找到平衡点.
  2. 看看你是否能够以纯解释模式运行你的应用程序(-Djruby.compile.mode = OFF).这应该摆脱填补你的permgen的大部分课程.
  3. 尝试使用Rails 2.2和更高版本threadsafe!模式运行.在单个运行时中运行应用程序是节省大量内存的另一种方法,这也适用于permgen.

编辑:仅供参考,这个问题原来是一个JRuby错误.1.5.2和1.6版本应解决此特定问题.我上面的评论仍然一般.