Complete JVM learning notes please click here

1. Core Overview

A process corresponds to one JVM instance, one run-time data area, and multiple threads that share the method area and heap, each containing program counters, local method stacks, and virtual machine stacks.

  1. There is only one heap memory per JVM instance, and the heap is also the core area of Java memory management
  2. The Java heap area is created at JVM startup and its size is determined. Is the largest chunk of memory managed by the JVM (the size of heap memory is adjustable)
  3. The Java Virtual Machine Specification states that the heap can be in memory space that is == physically discontinuous ==, but == logically it should be treated as continuous ==
  4. All threads share the Java heap and can also be allocated Thread Local Allocation Buffer (TLAB). No, TLAB threads are unique to the heap.)
  5. The Java Virtual Machine Specification describes the Java heap as: all object instances and arrays should be allocated on the heap at run time.
    • From a practical usage point of view, “almost” all instances of objects are allocated memory here (” almost “because they might be stored on the stack)
  6. Arrays or objects are never stored on the stack because the stack frame holds a reference to the location of the object or array in the heap
  7. Objects in the heap are not removed immediately after the method ends, but only during garbage collection
  8. The heap is the area where the Garbage Collection (GC) performs Garbage Collection

1.1 Configuring the JVM and Viewing JVM Processes

  • Write HeapDemo/HeapDemo1 code
public class HeapDemo {
    public static void main(String[] args) {
        System.out.println("start...");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end..."); }}Copy the code
  • First configure the virtual machine, as shown in Run-Edit Configurations

  • In the JDK directory, I was/Library/Java/JavaVirtualMachines jdk1.8.0 _171. JDK/Contents/Home/bin find jvisualvm run (or directly to the terminal operation jvisualvm), to check the process, You can see the configuration information we set up

  • You can see that HeapDemo configuration -xMS10M, the allocated 10M is allocated to the new generation 3m and the old 7m

1.2 Analyzing SimpleHeap JVMS

public class SimpleHeap { private int id; Public SimpleHeap(int id) {this.id = id; } public voidshow() {
        System.out.println("My ID is "+ id); } public static void main(String[] args) { SimpleHeap sl = new SimpleHeap(1); SimpleHeap s2 = new SimpleHeap(2); int[] arr = new int[10]; Object[] arr1 = new Object[10]; }}Copy the code

1.3 Subdivided memory structure of the heap

  • Before JDK 7: New area + endowment area + permanent area
    • Young Generation Space: It is divided into Eden zone and Survior zone ==Young/New==
    • Tenure generation Space: ==Old/Tenure==
    • Permanent Space: = =Perm= =

  • After JDK 8: new area + endowment area + meta space
    • Young Generation Space: It is divided into Eden zone and Survior zone ==Young/New==
    • Tenure generation Space: ==Old/Tenure==
    • The Meta Space: Meta = = = =

2. Set the heap memory size to OOM

  • The Java heap area is used to store Java object instances. The size of the heap is set at JVM startup and can be set with “-xmx” and “-xms”
    • -xms is used to represent the starting memory of the heap, equivalent to -xx :InitialHeapSize
      • -Xms sets the initial memory size of heap space (young generation + old generation)
        • -x is the running parameter of the JVM
        • Ms is the memory start
    • -xmx sets the maximum memory for the heap, equivalent to -xx :MaxHeapSize
  • An OOM exception will be raised if the heap size exceeds the maximum memory specified by -xmx
  • == the -xms and -xmx parameters are usually set to the same value. The purpose is to improve performance by eliminating the need to re-delimit the size of the heap after the Java garbage collection mechanism has cleaned up the heap
  • By default, the initial memory size is physical memory size /64. Maximum memory size: Physical memory size /4
    • Manual setting: -xMS600m -XMx600m
  • View the set parameters:
    • Method 1: == Enter JPS == and then ==jstat -GC process ID ==
    • Method two: (Console print) Edit Configurations->VM Options Add == -xx :+PrintGCDetails==

2.1 Viewing the Heap Memory Size

Public class HeapSpaceInitial {public static void main(String[] args) {// Returns the total heap memory in the Java VIRTUAL machine long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024; Long maxMemory = Runtime.geTruntime ().maxMemory() / 1024/1024; System.out.println("-Xms : " + initialMemory + "M"); //-Xms : 245M System.out.println("-Xmx : " + maxMemory + "M"); //-Xmx : 3641M System.out.println("System memory size:"+ initialMemory * 64.0/1024 +"G"); // System memory size: 15.3125g system.out.println ("System memory size:"+ maxMemory * 4.0/1024 +"G"); Thread.sleep(1000000); thread.sleep (1000000); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

2.2 Heap size analysis

Set the heap size to 600M, and the result is 575m. This is because the survivor zone S0 and S1 occupy 25m each, but one of them is always empty, holding the Eden zone and one survivor zone

2.3 OOM

Java. Lang. OutOfMemoryError: Java heap space code sample:

/** * -Xms600m -Xmx600m */ public class OOMTest { public static void main(String[] args) { ArrayList<Picture> list = new  ArrayList<>();while(true){ try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } list.add(new Picture(new Random().nextInt(1024 * 1024))); } } } class Picture{ private byte[] pixels; public Picture(int length) { this.pixels = new byte[length]; }}Copy the code

3. The Young and the old

  • Java objects stored in the JVM 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 lifetime, in some cases consistent with that of the JVM
  • The Java heap can be further subdivided into YoungGen and OldGen.

  • The young generation can be divided into Eden space, Survivor0 space and Survivor1 space (sometimes also called FRmo zone, to zone).

  • Configure the ratio of Cenozoic and old age in the heap structure

    • Default -xx: NewRatio=2, indicating that the Cenozoic era accounts for 1, the old age accounts for 2, and the Cenozoic era accounts for 1/3 of the whole heap
    • -xx :NewRatio=4, indicating that the Cenozoic era accounts for 1, the old age for 4, and the Cenozoic era accounts for 1/5 of the whole heap

  • In hotSpot, the default ratio of Eden space to two Survivor Spaces is 8:1:1 (6:1:1 at test time), and developers can adjust the ratio of Spaces with the option -xx :SurvivorRatio, such as -xx :SurvivorRatio=8

  • Almost all Java objects are created in Eden

  • The vast majority of Java objects are destroyed in the new generation (IBM research indicates that 80% of objects in the new generation are “dead”).

  • You can use the -xmn option to set the maximum memory size for the new generation.

The test code

/** * -xms600m -xmx600m ** -xx :NewRatio: Sets the ratio between the new generation and the old generation. The default value is 2. * -xx :SurvivorRatio: sets the ratio of Eden zones to Survivor zones in the new generation. The default value is 8 * -xx: -useadaptivesizePolicy: disables the adaptive memory allocation policyThe '-'Shut down,'+'Open * -xmn: Sets the size of the new generation space. * */ public class EdenSurvivorTest {public static void main(String[] args) {system.out.println ()"I just came by for a quick visit."); try { Thread.sleep(1000000); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

4. Diagram the object assignment process

4.1

For the new object allocate memory is a very precise and complicated task, the JVM’s designers not only need to consider how to allocate memory, where is the problem, 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 and the program needs to create objects again, the JVM’s garbage collector will perform a Minor GC on Eden garden, destroying objects in Eden garden that are no longer referenced by other objects. Load a new object and place it in the Garden of Eden
  3. Then move the remaining objects in Eden to Survivor 0.
  4. If garbage collection is triggered again, the last surviving item will be placed in Survivor 0, if not collected, it will be 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. · Parameters can be set: -xx :MaxTenuringThreshold= for setting.
  7. In the retirement area, relatively leisurely. When the memory of the elderly area is insufficient, GC: Major GC is triggered again to clean the memory of the elderly area.
  8. An OOM exception will be generated if the endowment area fails to save objects after performing Major GC.

conclusion

= =For survivor S0,s1: swap after copy, who is empty and who is to= =

= =About garbage collection: frequently collected in newborn area, rarely collected in endowment area, almost no longer collected in permanent area/meta-space.= =

4.2 Special cases of object allocation

4.3 Code Examples

public class HeapInstanceTest {
    byte[] buffer = new byte[new Random().nextInt(1024 * 200)];

    public static void main(String[] args) {
        ArrayList<HeapInstanceTest> list = new ArrayList<HeapInstanceTest>();
        while (true) { list.add(new HeapInstanceTest()); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }}}}Copy the code

Corresponding heap space allocation process

4.4 Common Tuning Tools

  • The JDK command line
  • Eclipse: 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 all three memory regions (new generation, old generation, method region), but most of the time the collection refers to the new generation.

In the implementation of hotSpot VM, there are two types of GC in the collection region: Partial GC and Full GC.

  • 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
      • Currently, only the CMS GC has a separate collection behavior for older generations
      • Note that the == Major GC is often confused with the Full GC
    • Mixed GC: Collects garbage from the entire new generation and part of the old generation
      • For now, the LATER G1 GC will have this behavior
  • Full GC: Collects the entire Java heap and method area garbage collection
  • Triggering mechanism of Minor GC:
    • When a young generation runs out of space, a Minor GC is triggered. When a young generation is full, that means Eden is full, and a Survivor full does not trigger a GC.(Each Minor GC cleans up the memory of a young generation, Survivor is passive GC, not active GC.)
    • Because Java formations are mostly ephemeral, Monor GC is very frequent and generally fast, which is clearly defined and easy to understand.
    • The Minor GC causes the STW (Stop the World) to suspend other users’ threads until the garbage collection is complete.
  • Old GC(Major GC/Full GC) trigger mechanism
    • A Major or Full GC occurs when an object disappears from the old age
    • The Major GC occurs, often accompanied by at least one Minor GC (not always, the Parallel Scavenge avenge strategy is used directly to select a Major GC).
      • That is, when the old decade runs out of space, the Minor GC is first attempted. If there is not enough space after that, the Major GC is triggered
    • Major GC is typically 10 times slower than Minor GC and has a longer STW
    • If there is not enough memory after Major GC, use OOM
  • Full GC triggering mechanism
    • Full GC execution can be triggered in one of five ways
      • ① When system.gc () is called, Full GC is recommended, but not necessarily executed
      • ② The old age space is insufficient
      • ③ Insufficient space in the method area
      • ④ The average size of the old age after passing the Minor GC is smaller than the available memory of the old age
      • ⑤ In the case of replication from Eden and Survivor S0 (from) to S1 (to), the object size is to Space available memory, so the object is saved to the old age, and the available memory of the old age is smaller than the object size
    • Note: Full GC is something to avoid during development or tuning, so that pause times are shorter

Code demo

Young GC ->Full GC -> OOM

+PrintGCDetails */ public class GCTest {public static GCTest {public static GCTest void main(String[] args) { int i = 0; try { List<String> list = new ArrayList<>(); String a ="testGC";
            while (true) {
                list.add(a);
                a = a + a;
                i++;
            }

        } catch (Throwable t) {
            t.printStackTrace();
            System.out.println("The number of iterations is:"+ i); }}}Copy the code

Log output

6. Generation idea of heap space

Why is the Java heap generational? It doesn’t work without generations

  • According to research, the life cycle of different objects is different. 70-99% of objects are temporary objects.
    • New generation: Eden and Survivor (S0,s1 is also called from to). To is always empty
    • Old age: Store objects that have survived many times 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. When the GC to find which objects was useless, it will scan all the sections of pile, and many objects are facing life in death, if a generational, put the newly created object in a certain place, when the GC to store the first “in life in death” object area for recycling, this will make a lot of space.

7. Memory allocation policy

  • If the object is still alive after Eden’s birth and after the first Minor GC and can be accommodated by Survivor, it will be moved to Survivor space, setting that to age the object 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 principles for different age groups are 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 sum of the size of all objects of the same age in the Survivor zone is greater than half of the size in the Survivor zone, objects older than or equal to that age can go straight to the old age. There is no need to wait until the age required in MaxTenuringThreshold
    • Space allocation guarantee
      • -XX: HandlePromotionFailure

Code sample

Allocate 60m heap space, the new generation is 20m, Eden is 16m, S0 is 2m, S1 is 2m, buffer object is 20m, Eden area cannot store buffer, directly promoted to the old age

/ * * test: -xms60m -XMX60m -xx :NewRatio= 2-xx :SurvivorRatio= 8-xx :+PrintGCDetails */ public class YoungOldAreaTest { // Cenozoic 20m, Eden 16m, s0 2m, S1 2m // old 40m public static void main(String[] args) {byte[] buffer = new byte[1024 * 1024 * 20]; //20m } }Copy the code

Log output

8. Allocating memory for objects: TLAB (Thread Private cache area)

TLAB (Thread Local Allocation Buffer)

  • 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
  • When multiple threads allocate memory simultaneously, TLAB can avoid a series of non-thread-safe problems and improve the throughput of memory allocation, so we can call this memory allocation method as fast allocation strategy
  • All JVMS derived from OpenJDK provide a TLAB design

instructions

  • Although not all object instances can successfully allocate memory in TLAB, the single JV is clearly the preferred memory allocation option
  • In the program, the developer can set the TLAB space to open with the option “-xx :UseTLAB”
  • By default, TLAB memory space is very small, only accounts for 1% of the whole EDen space and, of course, we can through the options “- XX: TLABWasteTargetPercent” set the percentage of EDen TLAB space occupies space size
  • When an object fails to allocate memory in TLAB space, the JVM attempts to ensure atomicity of data operations by using locking mechanisms, thereby allocating memory directly in Eden space

Code demo

  • The terminal enters the JSP to view the TLABArgsTest process ID
  • Jinfo-flag UseTLAB 64566 (process ID). -xx :+UseTLAB indicates that TLAB is enabled by default
Public class TLABArgsTest {public static void main(String[] args) {public static void main(String[] args) { System.out.println("I just came by for a quick visit."); try { Thread.sleep(1000000); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

TLAB object allocation process

9. Summarize heap space parameter Settings

  • -xx :PrintFlagsInitial: Displays the default initial values of all parameters
  • -xx :PrintFlagsFinal: View final values of all parameters (subject to change, no longer initial values)
    • The command to view a specific parameter:
      • JPS: View the current running process
      • Jinfo-flag SurvivorRatio process ID: Displays the ratio of Eden Spaces to S0/S1 Spaces in the new generation
  • -xms: initial heap memory (default: 1/64 of physical memory)
  • -xmx: maximum heap space memory (default: 1/4 of physical memory)
  • -xMN: Set the new generation size (initial value and maximum value)
  • -xx :NewRatio: Configures the proportion of new generation and old generation in the heap structure
  • -xx :SurvivorRatio: sets the ratio of Eden and S0/S1 Spaces in the new generation
  • -xx :MaxTenuringThreshold: Set the maximum age of garbage in the new generation (default: 15)
  • -xx :+PrintGCDetails: displays detailed GC processing logs
    • To display gc information, run the following command: ① -xx :+PrintGC ② -verbose: GC
  • – XX: HandlePromotionFailure: whether set space allocation

instructions

Before Minor Gc occurs, the virtual machine checks to see if the maximum available contiguous space of the old age is greater than the total space of all objects of the new generation.

  • If it is, the Minor GC is safe
  • If less than, the virtual opportunity view – XX: HandlePromotionFailure setting whether to allow guarantees failure. HandlePromotionFailure (true==)
    • If HandlePromotionFailure=true, it continues to check whether the maximum contiguous available space of the old age is greater than the average size of objects promoted to the old age over time.
      • √ If greater, a Minor GC is attempted, but this Minor GC is still risky;
      • √ If less than, perform a Fu11 GC instead.
    • √ If HandlePromotionFailure=false, do a Fu11 GC instead.

After JDK6 Update24 (JDK7), HandlePromotionFailure does not affect the virtual machine’s space allocation guarantee policy. But it is no longer used in code. The rule after JDK6 Update24 changes to == If the continuous space of the old generation is larger than the total size of the new generation object or the average size of the previous promotions, the Minor GC will be performed, otherwise the Full GC will be performed. = =

10. Is the heap the only option for allocating objects (no)

In understanding the Java Virtual Machine, Java heap memory is described as follows: As JIT compilation progresses and escape analysis techniques mature, == allocation on the stack, scalar replacement optimization == 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 == can be optimized to allocate == on the stack if, after Escape Analysis, an object is found to have 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(GCinvisible 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.

  • 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 analyzing object dynamic scope:
    • When an object is defined in a method and the == object 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.
  • == How to quickly determine if escape analysis has occurred by looking at whether the object entity of new is likely to be called outside the method ==

The code analysis

public void method(){
    V v = new V();
    //use V
    //......
    v = null;
}
Copy the code

Objects that do not escape can be allocated to the stack, and stack space is removed at the end of the method execution.

public static StringBuffer createStringBuffer(String s1,String s2){
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb;
}
Copy the code

Because the sb returned by the above method is used outside the method, an escape occurs. If you want to StringBuffer sb without escaping the method, you can write:

public static String createStringBuffer(String s1,String s2){
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb.toString();
}
Copy the code

Escape analysis

/** * Escape analysis ** How to quickly determine whether an escape analysis has occurred depends on whether the object entity of new is likely to be called outside the method. */ public class EscapeAnalysis { public EscapeAnalysis obj; /* The EscapeAnalysis method returns the EscapeAnalysis object. */ public EscapeAnalysisgetInstance() {returnobj == null? new EscapeAnalysis() : obj; } /* Assign a member attribute to escape */ public voidsetObj(){ this.obj = new EscapeAnalysis(); } // Consider: what if the current obj reference is declared static? Escape still happens. /* The scope of the object is only valid in the current method, no escape occurs */ public voiduseEscapeAnalysis(){ EscapeAnalysis e = new EscapeAnalysis(); } /* reference the value of a member variable, escape */ public voiduseEscapeAnalysis1(){ EscapeAnalysis e = getInstance(); //getInstance().xxx() will also escape}}Copy the code

Parameter Settings

  • Escape analysis is enabled by default in HotSpot after JDK 6U23
  • If an earlier version is used, developers can pass
    • -xx :DoEscapeAnalysis Explicitly enables escape analysis
    • -xx :+PrintEscapeAnalysis Displays the filtering results of escape analysis

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

Code optimization

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

  1. On-stack allocation: Converts heap allocation to stack allocation. If an object is allocated in a child thread so that Pointers to the object never escape, the object may be a candidate for stack allocation rather than heap allocation
  2. Synchronous elision: If an object is found to be accessible only from one thread, operations on the object may be performed without regard to synchronization
  3. Detached object or scalar substitution: Some objects may not need to exist as a contiguous memory structure and can be asked to store part (or all) of the object not in memory, but in CPU registers.

On the stack

  • 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 machine garbage collection
  • Common on-stack assignment scenarios: assigning a value to a member variable, returning a value from a method, passing an instance reference

The following code, turn off escape analysis (-xx: -doescapeAnalysi), maintain 10000000 objects, if escape analysis is enabled, only maintain a few objects (JDK7 escape analysis is enabled by default)

/** * StackAllocation test * -xmx1g-xms1g-xx: -doescapeanalysis -xx :+PrintGCDetails */ public class StackAllocation {public static void main(String[] args) { long start = System.currentTimeMillis();for(int i = 0; i < 10000000; i++) { alloc(); } long end = system.currentTimemillis (); System.out.println("The time spent is:" + (end - start) + " ms"); Sleep try {thread.sleep (1000000); } catch (InterruptedException e1) { e1.printStackTrace(); } } private static voidalloc() { User user = new User(); } static class User {}}Copy the code

Synchronous omit

  • The cost of thread synchronization is quite high, and the consequence of synchronization is reduced concurrency and performance
  • When a synchronized block is dynamically compiled, the JIT compiler can use escape analysis to determine whether the lock object used by the synchronized block can only be accessed by 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 ==
*/ public class SynchronizedTest {public voidf() { Object hollis = new Object(); synchronized(hollis) { System.out.println(hollis); }} // The hollis object is locked in the code, but the life of the hollis object is only in the f () method and is not controlled by other threads, so it will be optimized for JIT compilation. // Optimize to ↓ public voidf2() { Object hollis = new Object(); System.out.println(hollis); }}Copy the code

Separate objects or scalar substitutions

  • The Scalar 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 Aggregate ==, and an object is an Aggregate in Java because it 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, the object will be disassembled into several member variables to be replaced by JIT optimization. This process is called scalar substitution
public class ScalarTest {
    public static void main(String[] args) {
        alloc();   
    }
    public static void alloc(){Point Point = new Point(1,2); } } class Point{ private int x; private int y; public Point(int x,int y){ this.x = x; this.y = y; }}Copy the code

The code above, after the scalar substitution, will become

public static void alloc(){
    int x = 1;
    int y = 2;
}
Copy the code

As you can see, the aggregate Point is replaced by two scalars after the escape analysis and it is found that it does not escape. So what’s good about scalar substitution? This can greatly reduce the footprint of the heap. Because once you don’t need to create objects, you don’t need to allocate heap memory anymore. Scalar substitution provides a good basis for on-stack allocation.

The test code

/** * Scalar replacement tests * -XMx100m -Xms100m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-EliminateAllocations */ public class ScalarReplace { public static class User { public int id; // Scalar (cannot be broken into smaller data) public String name; } public static voidalloc() { User u = new User(); // There is no escape. u.name ="www.atguigu.com";
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            alloc();
        }
        long end = System.currentTimeMillis();
        System.out.println("The time spent is:" + (end - start) + " ms"); }}Copy the code

Summary of escape analysis

  • 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 fundamental reason is that there is no guarantee that the performance cost of escape analysis will be higher than its 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.
  • Although this technique is not very mature, it is also a very important tool in real-time compiler optimization.
  • 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. As far as I know, this is not done in Oracle HotspotJVM, as documented in escape analysis, so it is clear that all object instances are created on the heap.
  • The JDK has changed a lot. The cache of intern strings and static variables used to be allocated to the persistent generation, which has been replaced by the metadata section. However, the intern string cache and static variables are not transferred to the metadata area, but are allocated directly on the heap, so this is also consistent with the previous conclusion: == object instances are allocated on the heap ==.
  • The young generation is the region where objects are born, governor, and die, where an object is created, applied, collected by the garbage collector, and ends its life
  • Older generations prevent long-life objects, usually Java objects copied from Survivor zones. Of course, there are special cases where we know that normal objects will be allocated to TLAB. If the object is large, the JVM will try to allocate it directly to other locations in Eden. If the object can’t find enough contiguously free space in the new generation, the JVM will simply allocate to the old generation
  • When GC occurs only in the young generation, the act of collecting young objects 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



JVM learning code and notes

【 code 】 github.com/willShuhuan… JVM_02 Class loading subsystem JVM_03 Run time data area 1- [program counter + vm stack + local method stack] JVM_04 Local method interface JVM_05 Run time data area 2- heap JVM_06 run time data area 3- Method area JVM_07 JVM_08 Execution Engine JVM_09 String constant pool StringTable JVM_10 Garbage Collection 1- Overview + Related algorithm JVM_11 Garbage Collection 2- Concepts related to garbage collection JVM_12 Garbage collection 3- Garbage collector