Thursday, November 22, 2012

Java Memory Structure Explained


    Java Memory Structure

    The JVM memory consists of the following segments:

    • Heap Memory, which is the storage for Java objects
    • Non-Heap Memory, which is used by Java to store loaded classes and other meta-data
    • JVM code itself, JVM internal structures, loaded profiler agent code and data, etc.

    Heap
    The JVM has a heap that is the runtime data area from which memory for all class instances and arrays are allocated. It is created at the JVM start-up.
    The heap size may be configured with the following VM options:
    • -Xmx<size> - to set the maximum Java heap size
    • -Xms<size> - to set the initial Java heap size

    By default, the maximum heap size is 64 Mb.
    Heap memory for objects is reclaimed by an automatic memory management system which is known as a garbage collector. The heap may be of a fixed size or may be expanded and shrunk, depending on the garbage collector's strategy.

    Non-Heap
    Also, the JVM has memory other than the heap, referred to as non-heap memory. It is created at the JVM startup and stores per-class structures such as runtime constant pool, field and method data, and the code for methods and constructors, as well as interned Strings.
    Unfortunately, the only information JVM provides on non-heap memory is its overall size. No detailed information on non-heap memory content is available.
    The abnormal growth of non-heap memory size may indicate a potential problem, in this case you may check up the following:
    • If there are class loading issues such as leaked loaders. In this case, the problem may be solved with the help of Class loaders view.
    • If there are strings being massively interned. For detection of such problem, Allocation recording may be used.

    If the application indeed needs that much of non-heap memory and the default maximum size of 64 Mb is not enough, you may enlarge the maximum size with the help of -XX:MaxPermSize VM option. For example, -XX:MaxPermSize=128m sets the size of 128 Mb.


    Allocated and Used Memory
    Allocated and used memory sizes are shown on the graphs for both heap and non-heap.
    The allocated memory is an overall amount of memory allocated by the JVM, while used memory is the amount of memory which is actually in use.
    Obviously, the allocated memory cannot be less than the used memory. The exact amount of allocated memory is determined by the JVM internal strategies.

    Memory Generations in java heap
    HotSpot VM’s garbage collector uses generational garbage collection. It separates the JVM’s memory into and they are called young generation and old generation.

    Young Generation
    Young generation memory consists of two parts, Eden space and survivor space. Shortlived objects will be available in Eden space. Every object starts its life from Eden space. When GC happens, if an object is still alive and it will be moved to survivor space and other dereferenced objects will be removed.

    Old Generation – Tenured and PermGen
    Old generation memory has two parts, tenured generation and permanent generation (PermGen). PermGen is a popular term. We used to error like PermGen space not sufficient.
    GC moves live objects from survivor space to tenured generation. The permanent generation contains meta data of the virtual machine, class and method objects.

    What does the JVM do? The Java Virtual Machine has two primary jobs:

    1. Executes Code
    2. Manages Memory  
      This includes allocating memory from  the OS, managing Java allocation including heap compaction,
      and removal of garbaged objects 
    Besides the above, the JVM also does stuff like managing monitors.

    Very Basic Java Theory

    An object is created in the heap and is garbage-collected after there are no more references to it. Objects cannot be reclaimed or freed by explicit language directives. Objects become garbage when they’re no longer reachable from the root set (e.g static objects)


    Objects inside the blue square are reachable from the thread root set, while objects outside the square (in red) are not.
    The sequence of the garbage collection process is as follows:
    1. Root set tracing and figure out objects that are not referenced at all.
    2. Put the garbage objects from above in finalizer Q
    3. Run finalize() of each of these instances
    4. Free memory

    Infant mortality in Java
    Most of the objects (80%) in a typical Java application die young. But this may not be  true for your application. Hence there is a need to figure out this rough infant mortality number so that you can tune the JVM accordingly.


    JVM flavors
    The Sun JVM understands the options -classic, -client and -server
    • classic : disables the Hotspot JIT compiler.
    • client (default): activates the Hotspot JIT for "client" applications.
    • server: activates the "server" Hotspot JIT: it requires a fair amount of time to warm up, but delivers best performance for server.
    Don't forget that, if you use them, -server or -client must be the first argument to Java.

    The Hotspot JVM uses adaptive optimization
    • JVM begins by interpreting all code, but it monitors the HotSpot
    • Fires off a background thread that compiles hotspot bytecode to native code
    • Hotspot JVM is only compiling and optimizing the "hot spot". Hotspot JVM has more time than a traditional JIT to perform optimizations
    • The Hotspot JVM keeps the old bytecodes around in case a method moves out of the hot spot.
    Java Garbage Collector

    Sun Classic (1.1 JVM) ...for historical reasons
    • Mark, Sweep & Compact
        Mark: identify garbage
        Sweep: Find garbage on heap, de-allocate it
        Compact: collect all empty memory together
    • Eligibility for garbage collection is determined by walking across memory, determining reachability and then compacting the heap
    • Compaction is just copying the live objects so that they’re adjacent in memory
    • there’s one large, contiguous block of free memory
    • The main problem with classic mark, sweep and compact is that all other threads have to be suspended while the garbage collector runs
    • Pause time is proportional to the number of objects on the heap
    Sun HotSpot( 1.2+ JVM)
    • Sun improved memory management in the Java 2 VMs by switching to a generational garbage collection scheme.
    • The JavaHeap is separated into two regions(we will exclude the Permanent Generation for the time being):
       New Objects
       Old Objects
    • The New Object Regions is subdivided into three smaller regions:
       1. 
      Eden , where objects are allocated
       2. Survivor semi-spaces:  
      From and To
    •  The Eden area is set up like a stack - an object allocation is implemented as a pointer increment. When the Eden area is full, the GC does a reachability test and then copies all the live objects from Eden to the To region.
    •  The labels on the regions are swapped
    •  To becomes  From - now the  From area has objects.
    JVM Heap:
    Java Heap is divided into 3 generations: Young(Eden), Old(Tenured), and Permanent.

    Arrangement of generations:
    The diagram below shows how objects get created in New generation and then move to survivor Spaces at every GC run, and if they survive for long to be considered old, they get moved to the Tenured generation. The number of times an object need to survive GC cycles to be considered old enough can be configured.  

    By default, Java has 2 separate  threads for GC, one each for young(minor GC) and old generation(major GC). The minor GC (smaller pause, but more frequent) occurs to clean up garbage in the young generation, while  the major GC (larger pause, but less frequent) cleans up the  garbage  in the old  generation. If the major GC too fails to free required memory, the JVM increases the current memory to help create new object. This whole  cycle  can go on till the current memory reaches the MaxMemory for the JVM (default is 64MB for client JVM), after which JVM throws OutOfMemory Error.
    Permanent Generation
    Class information is stored in the perm generation. Also constant strings are stored there. Strings created dynamically in your application with String.intern() will also be stored in the perm generation.Reflective objects (classes, methods, etc.) are stored in perm. It holds all of the reflective data for the JVM

    JVM process memory

    The windows task manager just shows the memory usage of the java.exe task/process. It is not unusual for the total memory consumption of the VM to exceed the value of -Xmx   Managed Heap(java heap, PERM, code cache) + NativeHEAP +  ThreadMemory <= 2GB (PAS on windows) 
           Code-cache contains JIT code and hotspot code.
           ThreadMemory = Thread_stack_size*Num_threads.ManagedHeap: Managed by the developer.
         Java heap: This part of the memory is used when you create new java objects.     Perm: for relfective calls etc. 
    NativeHeap : Used for native allocations.ThreadMemory: used for thread allocations. 
            
    What you see  in the TaskManager is the total PAS, while what the profiler shows is the Java Heap and the PERM(optionally)
       
     Platforms                                     Maximum PAS*
      1. x86 / Redhat Linux 32 bit             2 GB
      2. x86 / Redhat Linux 64 bit             3 GB
      3. x86 / Win98/2000/NT/Me/XP        2 GB
      4. x86 / Solaris x86 (32 bit)              4 GB
      5. Sparc / Solaris 32 bit                   4 GB

No comments:

Post a Comment

Please feel free to post your queries here