1. Core concepts of the heap

Core overview of the heap

The heap is shared by threads, as is the method area (Runtime). They are private to the process and shared by the thread.

  • There is only one heap memory per JVM instance, and the heap is also the core area of Java memory management.

  • The Java heap area is created when JW is started and its size is determined. Is the largest chunk of memory managed by the JVM. The size of heap memory is adjustable.

  • The Java Virtual Machine Specification states that the heap can be in a physically discontinuous memory space, but logically it should be treated as continuous.

  • All threads share the Java heap, where Thread Local AIIocation buffers (TLAB) can also be partitioned.

  • The Java Virtual Machine Specification describes the Java heap as: all object instances and arrays should be allocated on the heap at run time.

    • “Almost” all object instances are here (The heap) Allocate memory. From the point of view of practical use.
  • Arrays and objects may never be stored on the stack because the stack frame holds a reference to the location of the object or array in the heap.

  • Objects in the heap are not removed immediately after the method ends, but only during garbage collection.

  • The heap is the area where the Garbage Collection (GC) performs Garbage Collection.

Memory segment

Most modern garbage collectors are designed on the basis of generational collection theory, and the heap space is subdivided into:

  • Java7 and its predecessors are divided into three parts: new + old + permanent

    • Young Generation Space Young/New. It is divided into Eden district and Survivor district.
    • Tenure Generation space Old/Tenure
    • Permanent Space Perm of the Permanent area
  • Java8 and later heap memory is logically divided into three parts: freshman area + endowment area + meta space

    • Young Generation Space Young/New. It is divided into Eden district and Survivor district.
    • Tenure Generation space Old/Tenure
    • Meta Space Meta Space

JDK 1.7 Internal structure of heap space

The permanent generation can be ignored. Think of it as a concrete implementation of the method area.

2. Set the heap memory size to OOM

Set up the

  • The Java heap area is used to store Java object instances, so the size of the heap is set at startup and can be selected-Xmx-XmsTo set it up.
    • -XmsUsed to represent the starting memory of the heap area, equivalent to-XX:InitialHeapSize
    • -XmxIs used to represent the maximum memory of the heap area, equivalent to-XX:MaxHeapSize
  • Once the size of memory in the heap exceeds-XmxThe OutOfMemoryErrory exception will be thrown when the maximum memory specified.
  • Will often-Xmx-XmsSet the two parameters to the same value.The goal is to improve performance by not having to re-delimit the size of the heap after the Java garbage collection mechanism has cleaned it up.
  • -Xmx-XmsThe values of the two parameter configurations are contained in the heap spaceYoung generation + old generation. Contains no permanent generation/meta-space.

The default

  • By default, initial memory size: physical computer memory size / 64; Maximum memory size: physical computer memory size / 4.

How do I view the set parameters

  • Method 1: Obtain the process ID by JPS. Jstat – INDICATES the ID of the GC process

  • Method 2: -xx :+PrintGCDetails

    The above two figures are viewed in different ways, but the results are the same.

3. The Young and the old

  • Java objects stored in can be divided into two classes.
    • One is transient objects with a short lifetime, which can be created and killed very quickly
    • The other class of objects has a very long life cycle and can be consistent with the life cycle of.
  • The Java heap area can be further divided into YoungGen and 01dGen.
  • The younger generation can be divided intoEdenSpace,survivor0Space andsurvivorl(Sometimes calledfromArea,toArea)
  • Allocation of Cenozoic and old age in reactor structure (Generally not modified)
    • The default-XX:NewRatio=2, indicating that the Cenozoic generation accounts for 1, the old age accounts for 2, and the Cenozoic generation accounts for 1/3 of the whole heap
    • Can be changed to-XX:NewRatio=4, indicating that the Cenozoic generation accounts for 1, the old age accounts for 4, and the Cenozoic generation accounts for 1/5 of the whole heap
  • In HotSpot, the default ratio of Eden space to the other two survivor Spaces is 8:1:1. You can go through the options-XX:SurvivorRatioAdjust the space ratio. Such as- XX: SurvivorRatio = 8
  • Almost allAll Java objects are newly generated in Eden.
  • Most destruction of Java objects occurs in the new generation.

According to a study by IBM, 80% of the new generation of adults die young.

  • You can use options-XmnSet the maximum memory size for the new generation. Use the default value for this parameter.
  • Although the default ratio of Eden to S0 and S1 in the new generation is 8:1:1, this may not be the case. There is an adaptive memory allocation policy. But if you use it explicitly- XX: SurvivorRatio = 8To specify the ratio, then the ratio must be true.

4. Object allocation process

4.1 an overview of the

For the new object allocate memory is a very precise and complicated task, Java’s designers not only need to consider how to allocate memory, where is the distribution problems, and because the memory allocation algorithm is closely related to the memory recovery algorithm, so you also need to consider the GC to perform after the memory recovery will produce memory fragments in the memory space.

  1. The new object is placed in the Garden of Eden first. This area has a size limit.
  2. When Eden fills up, the program needs to create objects again, and the JVM’s garbage collector does a YGC/Minor GC on the Eden garden, destroying objects in the Eden Garden that are no longer referenced by other objects. Load new objects and put them in Eden Garden.
  3. Then move the remaining objects in Eden to Survivor 0.
  4. If garbage collection is triggered again, the object that survived the last time is placed in Survivor 0, and if it is not collected, it is placed in Survivor 1.
  5. If the garbage collection is repeated, it will be put back into Survivor 0 and then go to Survivor 1.
  6. When can WE go to the nursing home? You can set the number of times. The default is 15.

You can set the following parameters: -xx :MaxTenuringThreshold=

To set the age when the object is moved to the old age.

  1. In the retirement area, relatively leisurely. When the memory of the endowment area is insufficient, GC: MajorGC is triggered again to clean the memory of the endowment area.
  2. If a Major GC is performed in the endowment area and the object is still unable to be savedOOMThe exception.
  3. Summary for survivor S0, S1: swap after copy, who is empty and who is to.
  4. About garbage collection: frequently collected in newborn area, rarely collected in endowment area, almost not collected in permanent area/meta-space.

4.2 Special Circumstances

4.3 Common Tuning Tools

  • JDK command line (jinfo, jstat, javap, jmap…)
  • EcIipse:Memory Analyzer Tool
  • Jconsole
  • VisualVM
  • Jprofiler
  • Java Flight Recorder
  • GCViewer
  • GC Easy

5. Minor GC、Major GC、Full GC

JVM GC does not always collect the above three memory regions (new generation, old generation, method region) together, but most of the time it collects for the new generation. In the implementation of HotSpot VM, there are two types of GC according to the collection region: Partial GC and FullGC.

  • Partial collection: Garbage collection that does not collect the entire Java heap. Which are divided into:
    • Minor GC/Young GC: This is just garbage collection for the new generation
    • Major GC (Old GC) : Just Old GC.
    • Mixed GC: Collects garbage from the entire new generation and part of the old generation. Currently, only the G1 GC has this behavior.

Currently, only the CMS GC has a separate collection behavior for older generations.

Note that there are many times when the Major GC is confused with the Full GC, and you need to be specific about whether it is old age or whole heap.

  • Full GC: Collects the entire Java heap and method area garbage collection.

Trigger conditions for the simplest generational GC strategy

1. Trigger mechanism of Minor GC:

  • Minor GC is triggered when the young generation runs out of space, where young generation full means Eden full,Survivor full does not raise GC(Each Minor GC cleans up the memory of the young generation.)
  • Because most Java objects are ephemeral, soMinor GC is very frequent, the general recovery speed is also relatively fast. This definition is clear and easy to understand.
  • The Minor GC raises the STW. Suspend other users’ threads until the garbage collection is complete.

The GC of S0 and S1 is passive. The trigger condition is Eden full.

2. Old GC(Major GC/Full GC) trigger mechanism:

  • Refers to GC that occurs in the old age, when the object disappears from the old age, we sayMajor GCFull GCHappened.
  • Major GC appears, often accompanied by at least one Minor GC (but not always, inparallel ScavengeThe collector’s collection policy has a direct Major selection process). This means that MinorGC will be tried first when there is not enough space in the old era. If the space is insufficient later, The gene is triggered № AJor GC.
  • MajorGC is typically 10 times slower than MinorGC,STW takes longer.
  • If MajorGC is not enough memory, use OOM.

Full GC trigger mechanism:

Full execution can be triggered in the following five ways:

  1. When system.gc() is called, FullGC is recommended, but not necessarily executed
  2. There is not enough space in the old era
  3. Method area space is insufficient
  4. The average size entering the old age after passing the Minor GC is greater than the memory available for the old age
  5. If the size of an object is larger than the available memory of To Space when the Eden or Survivor space0 (From Space) zone is copied To survivor space1 (To Space) zone, the object is migrated To the old age and the available memory of the old age is smaller than the size of the object.

Note: Full GC is something to avoid in development or tuning. This will shorten the time.

6. Generation idea of heap space

Why is AVA heap generation needed? Can’t it work without generations?

According to research, the life cycle of different objects is different. 70% to 99% of objects are temporary.

  • New generation: Eden and two survivor (also known as FROM /to, 50/51) of the same size, and T0 is always empty.
  • Old age: Stores objects that have survived multiple GC cycles in the New generation.

The only reason for generational is to optimize GC performance. If there is no generation, then all the objects are in one place, which is like putting all the people in one school in one classroom. To find out which objects are useless during GC, all areas of the heap are scanned. A lot of objects are dead, so if you put the new object in a certain place, when GC is the first time to collect the “dead” object area, this will free up a lot of space.

7. Memory allocation policy

If the object is still alive after Eden is born and after the first MinorGC and can be accommodated by survivor, it is moved to survivor space and the object age is set to 1. Each time an object survives MinorGC in a survivor zone, it increases in age by one year, and when it reaches a certain age (15 by default, which varies from JVM to GC), it is promoted to the old age.

The age threshold for the object to be promoted to the old age can be set with the option -xx: MaxTenuringThreshold.

The object allocation principle for different age groups is as follows:

  • Eden is assigned priority
  • Large objects are allocated directly to the old age (Try to avoid too many large objects in your program)
  • Long-lived objects are assigned to the old age
  • Dynamic object age determination
    • If the survivor zoneThe sum of all object sizes of the same age is greater than half of the survivor space, objects older than or equal to this age can directly enter the old age without waiting until the age specified in MaxTenur1ngThreshold.
  • All – party guarantees:- XX: Hand1ePromotionFailure

8. Allocating memory for objects: TLAB

Why TLAB (Thread Local Allocation Buffer) is available?

  • The heap is a thread shared area where any thread can access the shared data
  • Because object instances are created so frequently in the JVM, it is not thread-safe to partition memory from the heap in a concurrent environment
  • In order to avoid multiple threads operating on the same address, it is necessary to use mechanisms such as locking, which will affect the allocation speed.

What is a TLAB?

  • The Eden region continues to be partitioned from the perspective of the memory model rather than garbage collection, and the JVM allocates a private cache region for each thread, which is contained within Eden space.
  • Using TLAB can avoid a series of thread-safety problems while improving the throughput of memory allocation when multiple threads allocate memory simultaneously, so we can call this method of memory allocationQuick allocation 筻 omitted.
  • All JVMS derived from OpenJDK provide a TLAB design.

Additional notes from TLAB

  • Although not all object instances will be able to successfully allocate memory in TLAB, the JVM will be the first choice for memory allocation.
  • In the program, the developer can go through options--XX:+UseTLABSet whether to enable TLAB space (default)
  • By default, the TLAB space has very little memory, only 1% of the Eden space-XX:TLABwasteTargetPercentSet the percentage of Eden space occupied by TLAB space.
  • When an object fails to allocate memory in the TLAB space, the JVM tries to passUse the locking mechanismEnsure atomicity of data operations to allocate memory directly in Eden space.

9. Summary: Parameter setting of heap space

  • -xx :+PrintFlagsInitial: Displays the default initial values of all parameters
  • -xx :+PrintFlagsFinal: displays the final value of all parameters (subject to change, not the initial value).
    1. jps: Displays the running process
    2. Jinfo-flag Parameter Name Process ID
  • -xms: initial heap memory (default: 1/64 of physical memory)
  • -xmx: maximum heap space memory (default: 1/4 of physical memory)
  • -Xmn: Sets the size of the new generation. (Initial and maximum values)
  • -xx :NewRatio: Configures the ratio of the new generation to the old generation in the heap structure (default: 2). Cenozoic 1/3, old 2/3)
  • -xx :survivorRatio: set the ratio of Eden and S0/S1 Spaces in the new generation (default: 8)
  • -xx :MaxTenuringThreshold: sets the maximum age of garbage of the new generation
    • The maximum is 15. The default value for the Parallel collector is 15 and the default value for the CMS collector is 6.
  • -xx :+printGCDetails: displays detailed GC processing logs
    • ① -xx :PrintGC ② -verbose:gc Displays the same information
  • – XX: HandlePromotionFailure: whether set space allocation

HandlePromotionFailure parameter Description

Before MinorGC occurs, the virtual machine checks whether the maximum contiguous space available in the old age is greater than the total space of all objects in the new generation.

  • If it is, MinorGC is safe
  • If the value is smaller than the value, the VM views the value-XX:HandlePromotionFailureSet whether to allow guarantee failure.
    • If HandlePromotionFailure=true, it continuesCheck whether the maximum available continuous space of the old age is greater than the average size of objects promoted to the old age.
      • If it is, try a MinorGC, but this MinorGC is still risky.
      • If less than, a FullGC is performed instead.
    • If HandlePromotionFailure= fa1SE, do a FullGC instead.

After JDK6 Update24, the HandlePromotionFailure parameter no longer affects the virtual machine’s space allocation guarantee policy. But it is no longer used in code. After JDK6 Update24, MinorGC will be performed as long as the continuous space of the old generation is larger than the total size of the new generation or the average size of the previous promotions, otherwise FullGC will be performed.

10. Is the heap the only option for allocating objects

In understanding the Java Virtual Machine, Java heap memory is described as follows: As JIT compilation progresses and escape analysis techniques mature, on-stack allocation, scalar replacement optimization techniques will lead to subtle changes, and all objects allocated to the heap will become less “absolute”.

It is common knowledge in Java virtual machines that objects are allocated memory in the Java heap. However, there is a special case where an object can be optimized for stack allocation if, after Escape Ana1ysis, it is found that there is no Escape method. This eliminates the need to allocate memory on the heap and garbage collection. This is also the most common out-of-heap storage technique.

In addition, the aforementioned deep OpenJDK based customization of TaoBaoVM, where the innovative GCIH (GC Invisible Heap) technology implements off-heap to move long-lived Java objects from the heap to off-heap, In addition, GC cannot manage Java objects inside GCIH, so as to reduce the collection frequency of GC and improve the collection efficiency of GC.

** Escape analysis can only be enabled in Server mode. ** can be viewed using Java -version

Overview of Escape analysis

  • How to allocate objects on the heap to the stack requires the use of escape analysis.
  • This is a cross-function global data flow analysis algorithm that can effectively reduce the synchronization load and memory heap allocation stress in Java programs.
  • Through escape analysis, the Java Hotspot compiler can figure out how far a new object’s references are used to determine whether to allocate the object to the heap.
  • The basic behavior of escape analysis is the dynamic scope of the analysis object:
    • When an object is defined in a method and is used only inside the method, no escape is considered to have occurred.
    • An object is considered to have escaped when it is defined in a method and referenced by an external method. For example, as a call parameter to be passed elsewhere.

After JDK6u23, escape analysis is enabled in HotSpot by default. If you are using an earlier version, you can use:

  • options-XX:+DoEscapeAna1ysisExplicitly turn on escape analysis
  • Through the options-XX:+PrintEscapeAnalysisView the filter results of escape analysis.

Conclusion: If you can use local variables in your development, do not use definitions outside the method.

Escape analysis: Code optimization

Using escape analysis, the compiler can optimize code as follows:

  1. On the stack. Convert heap allocation to stack allocation. If an object is allocated in a subroutine so that Pointers to it never escape, the object may be a candidate for stack allocation, not heap allocation.
  2. Synchronous omit. If an object is found to be accessible only from one thread, operations on the object can be performed without regard to synchronization.
  3. Separate objects or scalar substitutions. Some objects may be accessible without needing to exist as a continuous memory structure, so some (or all) of the object can be stored not in memory, but in A CPU register (or stack in Java’s case).

1. Stack allocation

  • The JIT compiler, based on the results of escape analysis at compile time, finds that an object can be optimized for stack allocation if it does not escape the method. After allocation, execution continues in the call stack, and finally the thread terminates, the stack space is reclaimed, and the local variable object is reclaimed. This eliminates the need for garbage collection.
  • Common on-stack assignment scenarios: assigning a value to a member variable, returning a value from a method, passing an instance reference.

2. Synchronous omission (elimination)

  • 41. The cost of thread synchronization is quite high, and synchronization degrades concurrency and performance.
  • When compiling synchronized blocks dynamically, the JIT compiler can use escape analysisDetermines whether the lock object used by the synchronized block can be accessed by only one thread and not published to other threads. If not, the JIT compiler unsynchronizes the code when it compiles the synchronized block. This can greatly improve concurrency and performance. This unsynchronization process is called synchronization elision, also known as lock elimination.

3. Scalar substitution

A Scalar is a quantity which cannot be broken down into smaller quantities. Primitive data types in Java are scalars.

In contrast, data that can be decomposed is called aggregates. Objects in Java are aggregates because they can be decomposed into other aggregates and scalars.

In THE JIT stage, if an object is found not to be accessed by the outside world after escape analysis, then the OBJECT will be disassembled into several member variables contained in it to be replaced by JIT optimization. This process is called scalar substitution.

public class Test {
    public static void main(String[] args) {
        alloc();
    }   
    private static void alloc(a) {
        Point point = new Point(1.2);
        System.out.println("x = " + point.x + ", y = " + point.y);
    }
    static class Point {
        private int x;
        private int y;
        public Point(int x, int y) { x = x; y = y; }}}Copy the code

The alloc() method above, after a scalar substitution, becomes

private static void alloc(a) {
  int x = 1;
  int y = 2;
  System.out.println("x = " + x + ", y = " + y);
}
Copy the code

What are the benefits? Heap memory footprint can be greatly reduced. Because you don’t have to create objects, you don’t have to allocate memory.

Scalar substitution provides a good basis for on-stack allocation.

Parameter -xx :+EliminateAllocations: Turns on scalar substitutions (on by default), allowing objects to be split and allocated on the stack.

Escape analysis: immature

  • A paper on escape analysis was published in 1999, but it wasn’t implemented until JDK1.6, and the technology isn’t fully developed yet.
  • The root cause isThere is no guarantee that the performance cost of escape analysis will be higher than his cost. Scalar substitution, stack allocation, and lock elimination can be done after escape analysis. However, escape analysis itself also requires a series of complex analysis, which is actually a relatively time-consuming process.
  • An extreme example would be an escape analysis where no object is escape-free. Then the process of escape analysis is wasted.
  • The technology isn’t quite there yet, but it isReal-time compiler optimization is a very important technique.
  • Note that there is some argument that through escape analysis, the JVM allocates objects on the stack that will not escape, which is theoretically possible, but depends on the JVM designer’s choice. This is not done in the Oracle Hotspot JVM, as documented in escape analysis, so it is clear that all object instances are created on the heap.
  • Most of the books are still based on previous versions of JDK7, and the JDK has changed a lot. Intern string caches and static variables used to be assigned to persistent generations, which have been replaced by metadata sections. However, the cache and static variables of the INTERN string are not transferred to the metadata area, but are allocated directly on the heap, so this is also consistent with the previous point:Object instances are allocated on the heap.

summary

  • The young generation is the region where objects are born, grow, and die, where an object is created, applied, and finally collected by the garbage collector to end its life.
  • Older generations of objects with long life cycles are usually Java objects copied from survivor zones. Of course, there are special cases where we know that ordinary objects will be assigned to tLabs; If the object is large, the JVM will try to allocate it directly elsewhere in Eden. If the object is too large to find enough contiguous free space in the new generation, the JVM allocates it directly to the old generation.
  • When GC occurs only in the young generation, the act of reclaiming objects from the young generation is called MinorGC. When GC occurs in an older age, it is called MajorGC or FullGC. In general, MinorGC occurs much more frequently than MajorGC, meaning that garbage collection occurs much less frequently in older generations than in younger ones.

11. Reference links/other tools

1. JVM Parameters -Oracle official website

Arthas – An open source Java diagnostic tool