Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is memory never released in my Tomcat JRuby application?

I have a JRuby on Rails application which is running inside Tomcat (Warble). It uses a Java bridge to connect to a Progress(OpenEdge) application server... When I monitor the memory, it only keeps going up.

  • 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

What's the best way to get to the bottom of the problem here? I guess it could either be JRuby objects that aren't cleaned up, or something in the Java bridge or the Garbage collector that doesn't do its job...

Even if I let the process run for half an hour, the memory doesn't go down...

  • Is there a way to know which Objects are alive?
  • Are there free tools which are easy to use by which I can have more information on who is using all the memory?

By the way, I already have configured the Tomcat server to use more memory, but that's just delaying a heap space error...

EDIT: What I'm actually seeing is that Tomcat just uses all the memory that it can maximum use (Maximum memory pool). And it never releases it. Maybe it's just normal behavior... I've now set maximum to 256MB for example and in the Task Manager, the memory just stays around 256MB.

EDIT:

When creating a heap dump and letting eclipse analyze it with the Eclipse Memory Analyzer this is the report I'm getting. I think it's normal since the tool probably doesn't expect the whole JRuby story...

Problem Suspect 1

6.458 instances of "org.jruby.RubyClass", loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988" occupy 56.969.616 (31,78%) bytes.

Keywords org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988 org.jruby.RubyClass

Problem Suspect 2

10.597 instances of "org.jruby.internal.runtime.methods.DefaultMethod", loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988" occupy 22.182.112 (12,37%) bytes.

Keywords org.jruby.internal.runtime.methods.DefaultMethod org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988

Problem Suspect 3

3.144 instances of "org.jruby.RubyModule", loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988" occupy 21.226.816 (11,84%) bytes.

Keywords org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988 org.jruby.RubyModule

Problem Suspect 4

8.888 instances of "org.jruby.MetaClass", loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988" occupy 18.563.784 (10,35%) bytes.

Keywords org.jruby.MetaClass org.apache.catalina.loader.WebappClassLoader @ 0x700ec6988

like image 731
Lieven Cardoen Avatar asked Oct 21 '22 06:10

Lieven Cardoen


1 Answers

First of all: 256M Heap Space is not a lot for Java applications - especially as a full blown servlet container / app server is involved and (likely) lots of libraries.

Java typically does not hand memory back to the operating system - once allocated the memory is considered to be owned by the JVM. I believe there might be some implementations of memory management that hand back memory, but I've never seen them. My typical recommendation in production environments is to have -Xmx equal -Xms anyway (allocate all the memory you want the JVM to be able to allocate immediately)

Running out of Heap Space is a signal for one of two (or more) conditions: a) You have an application with a memory leak, b) you are not allocating enough for the application demand.

Raise memory allocation for your JVM and monitor the memory use and garbage collection to rule out b) - if you can safely say that your application has enough memory for its needs, hunt for a) and locate the root cause for the memory leak. You'll best use a profiler for that, but with 256M of memory, there's a great chance that you just have not enough memory.

like image 199
Olaf Kock Avatar answered Oct 28 '22 22:10

Olaf Kock