2

I'm debugging a memory problem on a Heroku dyno that has 512M of memory. After a lot of poking and prodding, I think I've narrowed it down to class space not getting cleaned up for some reason. Here's the output of jcmd <pid> VM.native_memory summary:

Java Heap (reserved=163840KB, committed=163840KB)
  (mmap: reserved=163840KB, committed=163840KB)


Class (reserved=1120210KB, committed=80466KB)
  (classes #14208)
  (malloc=2002KB #18418)

  (mmap: reserved=1118208KB, committed=78464KB)

Thread (reserved=26165KB, committed=26165KB)
  (thread #45)
  (stack: reserved=25776KB, committed=25776KB)
  (malloc=144KB #222)
  (arena=244KB #89)

Code (reserved=256694KB, committed=42130KB)
  (malloc=7094KB #10281)
  (mmap: reserved=249600KB, committed=35036KB)

GC (reserved=569KB, committed=569KB)
  (malloc=29KB #279)
  (mmap: reserved=540KB, committed=540KB)

Compiler (reserved=217KB, committed=217KB)
  (malloc=86KB #290)
  (arena=131KB #3)

Internal (reserved=3116KB, committed=3116KB)
  (malloc=3084KB #16726)
  (mmap: reserved=32KB, committed=32KB)

Symbol (reserved=19560KB, committed=19560KB)
  (malloc=15812KB #163798)
  (arena=3748KB #1)

Native Memory Tracking (reserved=3649KB, committed=3649KB)
  (malloc=292KB #4629)
  (tracking overhead=3357KB)

Arena Chunk (reserved=198KB, committed=198KB)
  (malloc=198KB)

Here are my JAVA_OPTS:

-Xmx160m
-Xss512k
-XX:MaxMetaspaceSize=128M
-XX:NativeMemoryTracking=detail
-XX:+UnlockDiagnosticVMOptions
-XX:+UseSerialGC

Any idea why Class is still reserving more than a gig of memory? Again, I'm not even totally sure class space is the issue, so any help is appreciated.

Note that I'm using some Groovy code, which can be fairly noisy in the classloader arena.

Andy
  • 8,749
  • 5
  • 34
  • 59
  • See this question https://stackoverflow.com/questions/31075761/java-8-reserves-minimum-1g-for-metaspace-despite-maxmetaspacesize I think your question is a duplicate of it. – Oleg Aug 05 '17 at 09:32
  • @Oleg Nice catch, but I'm using neither `-XX:+UseCompressedClassPointers` nor `-XX:+UseCompressedOops`, which would cause issues in this area, reserving the 1G as mentioned in the referenced question according to https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html#sthref66. My problem is different because the `CompressedClassSpaceSize` should not apply. – Andy Aug 05 '17 at 09:35
  • Can you check with `jcmd VM.flags` I think they are on by default. – Oleg Aug 05 '17 at 09:50
  • You are a life saver. Please add your answer and point to the other question. I'll mark it as the accepted answer. – Andy Aug 05 '17 at 09:55

1 Answers1

2

Java 8 is reserving 1GB of memory for compressed class pointers. If you want it to reserve less memory you can do that with CompressedClassSpaceSize jvm parameter. Some additional details in this answer and in this guide from oracle.

Note that from the oracle guide it looks like java only reserves 1GB when UseCompressedOops and UseCompressedClassesPointers jvm arguments are used but for some reason they decided not to mention that they are on by default.

Oleg
  • 6,124
  • 2
  • 23
  • 40