0

I have a large-ish Spray API written with about 60-70 endpoints, and I run it using the spray-can HTTP server on Java 7. While running a large number of automated end-to-end tests against it, I received a java.lang.OutOfMemoryError: PermGen space error.

I have managed to deal with the problem by forcing classes to be unloaded (using -XX:+CMSClassUnloadingEnabled), increasing the Max PermGen size to 1024m and setting the thread stack size to 2m. But I'm worried I'm masking my problems.

My questions are:

  • I thought the PermGen stored class metadata. I can understand how I might run out of PermGen space when compiling the code. But in this case, I didn't compile the code on the machine, and this error hit me a few minutes into running the application as mentioned above. Why?

  • Am I taking the right approach to deal with PermGen space errors? Are there recommended JVM flags for apps run using Spray-Can?

  • When using the CMSClassUnloadingEnabled, do I also need to use UseConcMarkSweepGC in Java 7? This question (CMSPermGenSweepingEnabled vs CMSClassUnloadingEnabled) appears to indicate it applies to Java 6.

Community
  • 1
  • 1
Siddhu
  • 888
  • 3
  • 9
  • 28
  • How are you deploying your Spray server ? – Soumya Simanta Jan 05 '15 at 18:09
  • Compiled and built into a ZIP using the Maven Assembly plugin, and subsequently packaged into an RPM and deployed. All of the Spray sources are in a JAR that I then call using java [options] WebApp (where WebApp is the Spray main class) – Siddhu Jan 05 '15 at 18:29
  • 2
    What is the size /number of classes (approx.) in the jar? It might truly be the case that you have so many classes that you are running out of perm gen. Here are a few generic recommendations to try out: 1. Use proguard to remove unwanted classes from your jar 2. Profile that application using something like VisualVM or YourKit 3. If you see PermGen go up, you can look at the classes in Permgen. 4. This will also tell you if you have any resource leaks (threads/DBConnection etc) in your code which often can lead to PermGen outofmemory errors. – Soumya Simanta Jan 05 '15 at 18:40
  • According to JVisualVM, we load about 10,000 classes into memory when we start up (using about 60 MB). So I guess I can see how we ended up causing the whole thing to run out of permgen space. I've set PermGen space to 128M and enabled HeapDumpOnOutOfMemory and set HeapDumpPath. Thanks for the tips! :-) – Siddhu Jan 06 '15 at 12:09

1 Answers1

1

It is possible that something in the framework - or by all means your code - is creating classes dynamically (proxies etc). I would suggest that you analyze a heap dump of the application after running a while, or preferably after crashing OutOfMemoryError. Instructions on how to create the dump can be found in this blog post of mine. The analyzis intructions may only be partially applicable in your case. After you have found what is filling up the PermGen, we can try to determine whether it is a leak that needs to be fixed/prevented, or whether you application is just large.

And yes, for -XX:+CMSClassUnloadingEnabled to have any effect you also need to enable the Concurrent Mark and Sweep garbage collector with -XX:+UseConcMarkSweepGC. However the default GC (usually Parallell in older JVMs and G1 in newer 1.7+) do class unloading by default, even though there seems to be a bug in the Parallell GC related to this.

Mattias Jiderhamn
  • 2,053
  • 1
  • 13
  • 6
  • Thanks, Mattias. That was helpful. We profiled our code following your instructions, and the app is now using a lot of PermGen space – Siddhu Jan 06 '15 at 12:06