Java 8 reserves minimum 1G for Metaspace despite (Max)MetaspaceSize

30,935

Solution 1

The reason why Java reserves 1G for Classes hides in the way how it manages compressed class pointers.

The long answer: read this doc https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html

The short answer: setup the correct size in 'CompressedClassSpaceSize' property -XX:CompressedClassSpaceSize=300m

Solution 2

Class (reserved=1221904KB

this isn't memory that's being used, just virtual address space

committed=197904KB

That's 197MB, not 1GB

Therefore you're not showing that java actually consumes 1GB of memory for class data, only that it reserves 1GB worth of address space.

Share:
30,935
Eugene To
Author by

Eugene To

Updated on June 29, 2020

Comments

  • Eugene To
    Eugene To almost 4 years

    Java 8 reserves 1G for Metaspace just after it starts. It means that minimum metaspace size is 1G. But I set up MetaspaceSize to 300m and MaxMetaspaceSize to 400m. Why Java reserves more then I allow?

    Java Version

    $ java -version
    java version "1.8.0_45"
    Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
    

    VM Flags

    $ jcmd 21689 VM.flags
    21689:
    -XX:CICompilerCount=3 -XX:ConcGCThreads=1 -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=62914560 -XX:+ManagementServer -XX:MarkStackSize=4194304 -XX:MaxHeapSize=1006632960 -XX:MaxMetaspaceSize=399998976 -XX:MaxNewSize=603979776 -XX:MetaspaceSize=299999232 -XX:MinHeapDeltaBytes=1048576 -XX:NativeMemoryTracking=summary -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC 
    

    NMT

    [jetty9-proxy@bm01 bin]$ jcmd 21689 VM.native_memory
    21689:
    
    Native Memory Tracking:
    
    Total: reserved=2769543KB, committed=1311159KB
    
    -                     Class (reserved=1221904KB, committed=197904KB)
                                (classes #36543)
                                (malloc=3344KB #44041) 
                                (mmap: reserved=1218560KB, committed=194560KB) 
    

    And just after start it was

    Total: reserved=2402748KB, committed=150796KB     
    
    -                     Class (reserved=1056956KB, committed=7868KB)
                                (classes #1300)
                                (malloc=188KB #564) 
                                (mmap: reserved=1056768KB, committed=7680KB) 
    
  • Eugene To
    Eugene To almost 9 years
    Yes, you are right. That is what I meant. Sorry, English is not my native language. I'll edit the topic.
  • Eugene To
    Eugene To almost 9 years
    But It should not reserve so much memory because I set up MetaspaceSize=300m and MaxMetaspaceSize=400m. Unpredictable reservation is bad. I have other JMV processes on that VM and I can't start them because there is no free memory.
  • the8472
    the8472 almost 9 years
    you can just turn on overcommit to allow it to reserve that much space.
  • Eugene To
    Eugene To almost 9 years
    This is a possible workaround. But I want to understand why java reserves 1G for Classes in the first place.
  • the8472
    the8472 almost 9 years
    I think that may have something to do with it needing a contiguous block of memory for compressed class space, which you are using. There's the CompressedClassSpaceSize option.
  • Andrei Damian-Fekete
    Andrei Damian-Fekete over 4 years
    I also liked this detailed explanation about why CompressedClassSpaceSize is a hard limit: stuefe.de/posts/metaspace/what-is-compressed-class-space
  • Rafael
    Rafael over 2 years
    BEWARE ... this answer might be wrong. If you are using a limited and small metaspace and the value of the metaspace is smaller than XX:CompressedClassSpaceSize then that option might be ignored and JVM might use the formula CompressedClassSpaceSize = MaxMetaspaceSize – 2 * InitialBootClassLoaderMetaspaceSize