Search code examples
javajvmjava-8jvm-hotspotmetaspace

Java8 metaspace & heap usage


I have this code to generate class dynamically and load it

import javassist.CannotCompileException;
import javassist.ClassPool;

public class PermGenLeak {
    private static final String PACKAGE_NAME = "com.jigarjoshi.permgenleak.";

    public static void main(String[] args) throws CannotCompileException, InterruptedException {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            ClassPool pool = ClassPool.getDefault();
            pool.makeClass(PACKAGE_NAME + i).toClass();
            Thread.sleep(3);
        }

    }
}

I launched this class against Java 7 (jdk1.7.0_60) and as expected it filled up PermGenSpace and heap remained unused Java 7 memory usage image shows permgen usage overtime and at the end JVM was terminated

Now the same code ran against Java 8 (jdk1.8.0_40-ea) and as expected it kept expanding native memory (Metaspace) but surprisingly for 1g of Metaspace it consumed 3g of Heap in OldGen (almost 3x of Metaspace maintained over time)

Java8 memory usage image shows Metaspace usage overtime and System memory usage sample

this email from Jon Masamitsu and this JEP ticket says

interned String and Class stats and some misc data has been moved to Heap

what exactly makes this increase in heap as it loads more classes into Metaspace ?


Solution

  • Run jmap -histo PID to see which objects consume the Heap Space.
    When I ran your example I saw the heap full of Javassist auxiliary objects:

     num     #instances         #bytes  class name
    ----------------------------------------------
       1:        592309      312739152  [Ljavassist.bytecode.ConstInfo;
       2:       6515673      208501536  java.util.HashMap$Node
       3:       2964403      169188824  [C
       4:       1777622      102165184  [Ljava.lang.Object;
       5:       4146200       99508800  javassist.bytecode.Utf8Info
       6:       3553889       85293336  java.util.ArrayList
       7:       2964371       71144904  java.lang.String
       8:        593075       56944008  java.lang.Class
       9:        592332       47388032  [Ljava.util.HashMap$Node;
      10:        592309       37907776  javassist.bytecode.ClassFile
      11:        592308       37907712  javassist.CtNewClass
      12:       1185118       28555808  [B
      13:        592342       28432416  java.util.HashMap
      14:       1184624       28430976  javassist.bytecode.ClassInfo
      15:        592309       28430832  [[Ljavassist.bytecode.ConstInfo;
      16:        592322       23692880  javassist.bytecode.MethodInfo
      17:        592315       23692600  javassist.bytecode.CodeAttribute
      18:        592434       18957888  java.util.Hashtable$Entry
      19:        592309       18953888  javassist.bytecode.ConstPool
      20:        592308       18953856  java.lang.ref.WeakReference
      21:        592318       14215632  javassist.bytecode.MethodrefInfo
      22:        592318       14215632  javassist.bytecode.NameAndTypeInfo
      23:        592315       14215560  javassist.bytecode.ExceptionTable
      24:        592309       14215416  javassist.bytecode.LongVector
      25:        592309       14215416  javassist.bytecode.SourceFileAttribute
      26:        592507        9487584  [I
      27:             8        6292528  [Ljava.util.Hashtable$Entry;
      28:           212          18656  java.lang.reflect.Method
      29:           407          13024  java.util.concurrent.ConcurrentHashMap$Node
      30:           124           8928  java.lang.reflect.Field