mabi
mabi

Reputation: 5306

Why would jmap -permstat report more than MaxPermSize bytes used?

I've taken a the jmap -permstat output of a JVM (reported as version 24.76-b04), it reports the following totals:

total = 5190 76930 1031431696 N/A alive=1, dead=5189 N/A

Which should be the number of entries, classes using this information, bytes used for metadata and liveness information.

Now, I wonder why it would report 1031431696 bytes, just shy of a Gigabyte when I startup my VM with -XX:MaxPermSize=256m. Can someone shed light on how the number is calculated?

Don't know if it's relevant but this is using Rhino with ~3k entries being DefiningClassLoaders.

Upvotes: 2

Views: 248

Answers (1)

K Erlandsson
K Erlandsson

Reputation: 13696

I have looked a bit at the code for the jmap -permstat implementation. The bytes used value is an estimation based on sizes for the different types of data a classloader loads (methods, fields, interfaces etc).

The top level method that does the size calculation for a loaded class is sun.jvm.hotspot.tools.PermStat.computeSize:

private long computeSize(InstanceKlass k) {
  long size = 0L;

  // the InstanceKlass object itself
  size += k.getObjectSize();

  // Constant pool
  ConstantPool cp = k.getConstants();
  size += cp.getObjectSize();
  size += objectSize(cp.getCache());
  size += objectSize(cp.getTags());

  // Interfaces
  size += arraySize(k.getLocalInterfaces());
  size += arraySize(k.getTransitiveInterfaces());

  // Inner classes
  size += objectSize(k.getInnerClasses());

  // Fields
  size += objectSize(k.getFields());

  // Methods
  ObjArray methods = k.getMethods();
  int nmethods = (int) methods.getLength();
  if (nmethods != 0L) {
     size += methods.getObjectSize();
     for (int i = 0; i < nmethods; ++i) {
        Method m = (Method) methods.getObjAt(i);
        size += m.getObjectSize();
        size += objectSize(m.getConstMethod());
     }
  }

  // MethodOrdering - an int array that records the original
  // ordering of methods in the class file
  size += arraySize(k.getMethodOrdering());

  return size;
}

My guess is that this estimation fails horribly in your case. The reason it fails is hard to say without checking the object size calculations in detail for your JVM version in combination with the characteristics of the loaded classes in your application.

Also, the Troubleshooting Guide for Java SE 6 with HotSpot VM mentions that the value is an approximation.

Bottom line, take the bytes used value with a grain of salt.

Upvotes: 1

Related Questions