JVM (Java Virtual Machine)

Posted by gkostenarov on Mon, 21 Feb 2022 16:20:45 +0100

7. Mnemonic

Decompile class files through javap:
Enter the class file directory and enter: javap -c class name.

Related mnemonic

  • aload_0:
    • A reference type is loaded.
    • First letter: a: reference type, i: integer type, l: long integer type
    • 0: indicates the 0th variable.
  • invokespecial: including init, private and super Method (), where < init > represents the initialization method.
  • getstatic: get static members.
  • bipush: - 128 ~ 127 integer range (8-bit signed integer, 256), put it on the top of the stack.
  • sipush: the range of integers less than - 128 and greater than 127 (16 bit signed integers) is put at the top of the stack.
  • iconst_m1: indicates - 1 and is placed at the top of the stack.
  • iconst_0 ~ iconst_5: It means 0 ~ 5 and put it on the top of the stack.
  • ldc: int float String constant, put it at the top of the stack.
  • ldc2_w: The long double constant is placed at the top of the stack.

8. Four reference levels of JVM

If an object has a reference to it, the object will not be recycled by GC?

Answer: not necessarily. It has limitations. It only applies to strong references. Soft references will be recycled by GC when memory space is insufficient, and weak references will be recycled as long as GC occurs.

The four strong references are: strong reference > soft reference > weak reference > virtual reference.

  • Except for strong references, the other three references inherit from a parent class reference < T >.
  • Soft reference, weak reference, phantom reference, and FinalReference.
  • There is a get method in Reference, which is used to return the Reference object.

(1) Strong reference

Object obj = new Object();
Conventions: reference obj and new Object();

There are two situations in which strong reference objects fail:

  1. End of life cycle (scope invalidation)
public void f() {
	Object obj = new Object();
}// After the method is executed, the reference object (new Object()) pointed to by the strong reference will be waiting to be recycled by GC.
  1. Set reference to null
public void f() {
	Object obj = new Object();
	// After setting the obj reference to null, the reference object will lose the reference point, and (new Object()) will be recycled by GC.
	obj = null;
}

Note: except for the above two cases, GC will not recycle reference objects at any time.

(2) Soft reference

Recycling mechanism: when the JVM is out of memory, GC will actively recycle soft reference objects.

Examples of soft references being recycled by GC:

import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) throws Exception {
        // Create a soft reference object, using the decoration mode: wrap the object layer by layer
        SoftReference<Object> soft = new SoftReference<>(new Object());
        List<byte[]> list = new ArrayList<>();

        // Start a thread to judge whether the soft reference object is recycled
        new Thread(() -> {
            try {
                // Sleep the thread for 100ms
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // Get the soft reference object. If it is null, it indicates that it has been recycled (it will be recycled if there is insufficient memory)
            if (soft.get() == null) {
                System.out.println("Soft references are recycled");
                System.exit(0);
            }
        }).start();

        // Keep adding data to the list collection until the heap overflows
        while (true) {
            if (soft.get() != null)
                // Add 1M at a time
                list.add(new byte[1024 * 1024]);
        }
    }
}

(3) Weak reference

Recycling mechanism: as long as GC is executed, weak reference objects will be recycled.

import java.lang.ref.WeakReference;

public class Main {
    public static void main(String[] args) {
        // Create a weak reference object
        WeakReference<Object> weak = new WeakReference<>(new Object());
        System.out.println(weak.get() == null ? "Recycled" : "Not recycled");
        // It is recommended that GC perform a recycle (probability of existence)
        System.gc();
        System.out.println(weak.get() == null ? "Recycled" : "Not recycled");
    }
}

The implementation results are:
Not recycled
Recycled

(4) Phantom reference

Also known as phantom reference or ghost reference.

  • Whether to use a virtual reference has nothing to do with the reference itself.
  • Cannot get the object itself through a virtual reference.
  • Null when getting the virtual reference object through the get() method, get() - > null.
  • Virtual references are not used alone. They are generally used together with reference queues.

Virtual reference value:

When GC reclaims a virtual reference object, it will put the virtual reference into the reference queue, and then (when the reference is out of the queue) reclaim the object. Therefore, we can use virtual reference and reference queue implementation.

Some additional operations are performed before the object is GC.
GC = > if there is a virtual reference = > virtual reference in queue = > virtual reference out of queue = > recycle object

Verify the series of operations performed before the virtual reference is recycled by GC.

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

/**
 * The following actions occur before the virtual reference performs GC:
 * GC -> Virtual reference queue - > virtual reference queue - > GC recycle
 */
public class Main {

    public static void main(String[] args) {
        Object obj = new Object();
        // Create a reference queue
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        // Create a virtual reference object
        PhantomReference<Object> phantomObject = new PhantomReference<>(obj, queue);
        // Judge whether the object is in the queue. There is no queue here, and the output is null
        System.out.println(queue.poll());
        // Set the strong reference object to null and it will be recycled after passing GC
        obj = null;
        // A GC recycle was performed
        System.gc();
        System.out.println("GC Yes...");
        // After GC is executed, the object will be queued and output here as the object address
        System.out.println(queue.poll());

    }
}

Special case: if the virtual reference object overrides the finalize() method, the JVM will delay the queue time of the virtual reference.

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

/**
 * The following actions occur before the virtual reference performs GC:
 * GC -> Virtual reference queue - > virtual reference queue - > GC recycle
 */
public class Main {

    public static void main(String[] args) {
        PhantomObject obj = new PhantomObject();
        // Create a reference queue
        ReferenceQueue<PhantomObject> queue = new ReferenceQueue<>();
        // Create a virtual reference object
        PhantomReference<PhantomObject> phantomObject = new PhantomReference<>(obj, queue);
        // Judge whether the object is in the queue. There is no queue here, and the output is null
        System.out.println(queue.poll());
        // Set the strong reference object to null and it will be recycled after passing GC
        obj = null;
        // After the cycle, it was delayed to the fourth time to join the team
        for (int i = 0; i < 5; i++) {
            // A GC recycle was performed
            System.gc();
            System.out.println((i + 1) + " GC Yes...");
            // After GC is executed, the object will be queued and output here as the object address
            System.out.println(queue.poll());
        }
    }
}

class PhantomObject{
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize About to be GC recovery...");
    }
}

Final reference

Use Finalizer to automatically recycle some unnecessary objects, such as construction methods.

// There is only one implementation class Finalizer:
final class Finalizer extends FinalReference<Object>

9. Use a reference to implement the elimination strategy of cache

  • Purpose: store the database data in the cache. When the cache reaches 90%, it needs to be reduced to 60%.
  • It can be realized by LRU algorithm.
  • General elimination strategy: eliminate according to the capacity (number of caches) + LRU.

By wrapping the object as a soft reference (the soft reference will be recycled when there is insufficient memory) and storing it in the cache.

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

/**
 * Advantages of this procedure:
 * When the JVM is out of memory, GC will automatically recycle soft references,
 * Therefore, this procedure does not need to consider the OOM (Out Of Memory) problem.
 */
public class Main1 {

    Map<String, SoftReference<Student>> caches = new HashMap<>();

    public static void main(String[] args) {
        SoftReference<Student> stu = new SoftReference<>(new Student());

    }
    /**
     * Put student information into cache
     * @param id
     * @param stu
     */
    void setCaches(String id, Student stu) {
        caches.put(id, new SoftReference<>(new Student()));
    }
    /**
     * Get student information from cache
     * @param id
     * @return
     */
    Student getCaches(String id) {
        return caches.get(id) == null ? null : caches.get(id).get();
    }
}
class Student{}

10. Parental delegation

Parents:

  • The loader of the JVM (included in the JVM and written in c + +).
  • User defined loader (independent of loader outside JVM, written in java).

Loader Description:

  • JVM comes with loader
    • Root loader (Bootstrap): load jdk\jre\lib\rt.jar (including most of the API s used to write code); You can specify to load a jar (- Xbootclasspath = xx.jar).
    • Extension: load jdk \ JRE \ lib \ ext * Jar (including the extension jar package in jdk); Loading can be specified (- Djava.ext.dirs = xx.jar).
    • System loader / Application Loader (System/App): load classpath (self written class); Loading can be specified (- Djava.class.path = class / jar).
  • Custom loader
    • Are subclasses of this abstract class (java.lang.ClassLoader)

delegate:

  • When a loader wants to load a class, if it can't load it by itself.
  • It will be loaded up by the parents layer by layer. When a loader of the parents is loaded successfully, it will return to success downward.
  • If all parents and themselves cannot load, an exception will be thrown.

(1) bootstrap root loader case:

public class Main {
    public static void main(String[] args) throws Exception {
        // Object is a class in rt.jar package
        Class obj = Class.forName("java.lang.Object");
        ClassLoader bootstrap = obj.getClassLoader();
        // The print is null, so the root loader is used
        System.out.println(bootstrap);
    }
}

The print is null. Click getClassLoader to see the source code annotation as follows:

/**
  * Returns the class loader for the class.  Some implementations may use
  * null to represent the bootstrap class loader. This method will return
  * null in such implementations if this class was loaded by the bootstrap
  * class loader.
  * /

Translate:
Returns the class loader for this class. Some implementations may use null to represent the bootstrap class loader. If this class is loaded by bootstrap, this method will return null in this class implementation.

It means that the bootstrap root loader is used by returning null.

(2) app Application Loader case:

public class Main {
    public static void main(String[] args) throws Exception {
        // The custom class is in the classpath
        Class myClass = Class.forName("org.gxuwz.arithmatic.lanqiao.MyClass");
        ClassLoader app = myClass.getClassLoader();
        // The print out is "sun.misc.launcher"$ AppClassLoader@18b4aac2 ", app loader
        System.out.println(app);
    }
}
class MyClass {}

Printed out are:
sun.misc.Launcher$AppClassLoader@18b4aac2

Indicates that the AppClassLoader loader is used.
be careful:

  • Define class loading: finally, the actual class loader is loaded.
  • Initialize class loading: the loader that loads the class for the first time.

Why is an App loader also called a System loader

public class Main {
    public static void main(String[] args) throws Exception {
        // Get system loader print results
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        // Get Application Loader print results
        Class myClass = Class.forName("org.gxuwz.arithmatic.lanqiao.MyClass");
        ClassLoader app = myClass.getClassLoader();
        System.out.println(app);
    }
}
class MyClass {}

No matter whether it is printed by the system loader or the Application Loader, the two printing results are consistent. They are both AppClassLoader Application Loader:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2

Get the parent loader layer by layer from the Application Loader:

public class Main {
    public static void main(String[] args) throws Exception {
        // Get app loader app
        Class myClass = Class.forName("org.gxuwz.arithmatic.lanqiao.MyClass");
        ClassLoader app = myClass.getClassLoader();
        System.out.println(app);
        
        // Get the parent loader of the application loader - > extension loader extension
        ClassLoader parent1 = app.getParent();
        System.out.println(parent1);

        // Get the parent loader - > root loader bootstrap of the extension loader
        ClassLoader parent2 = parent1.getParent();
        System.out.println(parent2);

        // Get parent loader of root loader - > none
        ClassLoader parent3 = parent2.getParent();
        System.out.println(parent3);
    }
}
class MyClass {}

The printing results are as follows:
Application Loader app - > extension loader - > root loader bootstrap - > none

(3) View class loader source code

(1) Class loader loads according to binary names:

// Normal package class name
"java.lang.String"
// $indicates anonymous inner class: DefaultEditor, an anonymous inner class under the JSpinner package
"javax.swing.JSpinner$DefaultEditor"
// The first anonymous inner class in the FileBuilder inner class
"java.security.KeyStoreBuilderBuilderFileBuilder$1"
// The first inner class of the third inner class in the URLClassLoader package
"java.net.URLClassLoader$3$1"

(2) Loader type of array

  • The loader type of the array is the same as that of the array element loader.
  • Arrays of native types (not classes, such as int, long...) have no loaders.

Class loader array description source document:

/**
 * <p> <tt>Class</tt> objects for array classes are not created by class
 * loaders, but are created automatically as required by the Java runtime.
 * The class loader for an array class, as returned by {@link
 * Class#getClassLoader()} is the same as the class loader for its element
 * type; if the element type is a primitive type, then the array class has no
 * class loader.
 * /

General meaning:
The class loader of the returned array class is the same as that of its element type; If the element type is the original type, the array class has no class loader.

Use an example to verify:

public class Main {
    public static void main(String[] args) throws Exception {
        MyClass[] cls = new MyClass[1];
        MyClass cl = new MyClass();
        // Array loader
        System.out.println(cls.getClass().getClassLoader());
        // Array element loader
        System.out.println(cl.getClass().getClassLoader());

        int[] arr = new int[1];
        // Primitive type array loader
        System.out.println(arr.getClass().getClassLoader());
        // Primitive type array element loader
        System.out.println(int.class.getClassLoader());
    }
}
class MyClass {}
  • Because the native type is a basic data type and not a class, the class loader cannot load.
  • If it is null, there are two possibilities. One is that there is no loader, and the other is that the loading type is root loader.

Output result:

(3)xx.class files may exist locally, from the network, or dynamically generated at runtime.

/**
 * <p> However, some classes may not originate from a file; they may originate
 * from other sources, such as the network, or they could be constructed by an
 * application.
 * /

(4) If the class file comes from a network, you need to inherit the ClassLoader parent class and override the findClass() and loadClassData() methods.

/**
 * <p> The network class loader subclass must define the methods {@link
 * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
 * from the network.  Once it has downloaded the bytes that make up the class,
 * it should use the method {@link #defineClass <tt>defineClass</tt>} to
 * create a class instance.  A sample implementation is:
 *
 * <blockquote><pre>
 *     class NetworkClassLoader extends ClassLoader {
 *         String host;
 *         int port;
 *
 *         public Class findClass(String name) {
 *             byte[] b = loadClassData(name);
 *             return defineClass(name, b, 0, b.length);
 *         }
 *
 *         private byte[] loadClassData(String name) {
 *             // load the class data from the connection
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote>
 * /

(4) Implementation of custom class loader

You need to inherit ClassLoader class and override findClass() and loadClassData() methods. findClass() calls loadClassData() method.

import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import java.io.File;
import java.io.FileInputStream;

public class Main1 extends ClassLoader {

    // The default construction method uses the root loader getSystemClassLoader()
    public Main1() {
        super();
    }

    // Customize the loader used
    public Main1(ClassLoader parent) {
        super(parent);
    }

    public Class findClass(String name) {
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }

    private byte[] loadClassData(String name) {
        name = splitDot("out.production.MyProject_02_arithmetic." + name) + ".class";
        FileInputStream inputStream = null;
        ByteOutputStream outputStream = null;
        byte[] res = null;
        try {
            // Get file data from file input stream
            inputStream = new FileInputStream(new File(name));
            // Get output stream
            outputStream = new ByteOutputStream();
            // Create buffer
            byte[] buf = new byte[2];
            int len = -1;
            // Loop outputs the buffer to the output stream
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
            // Returns an array of output stream bytes
            res =  outputStream.getBytes();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (inputStream != null) inputStream.close();
                if (outputStream != null) outputStream.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    // Set "." Replace with "/"
    private String splitDot(String s) {
        return s.replace(".", "/");
    }

    public static void main(String[] args) throws Exception {
        Main1 main1 = new Main1();
        Class myClass = main1.loadClass("org.gxuwz.arithmatic.lanqiao.MyClass");
        System.out.println(myClass.getClassLoader());
        MyClass myClass1 = (MyClass)(myClass.newInstance());
        myClass1.hello();
    }
}
class MyClass{
    public void hello() {
        System.out.println("hello...");
    }
}

be careful:

  • loadClassData(String name) is the text form string a / B / MyClass Class and starts with out production…
  • findClass(String name) is the full class name form a.b.MyClass, and the beginning is: package name Class name class.

The above code still prints out the APP loader: sun misc. Launcher$ AppClassLoader@18b4aac2 , because MyClass The class file is in the classpath, so the application loader is still used. You need to move it to an external directory, such as D: / MyClass Class, which will trigger the custom loader as follows. The path is mainly modified, and the class file in the classpath needs to be deleted:

import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import java.io.File;
import java.io.FileInputStream;

public class Main1 extends ClassLoader {

    private String path;

    // The default construction method uses the root loader getSystemClassLoader()
    public Main1() {
        super();
    }

    public Class findClass(String name) {
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }

    private byte[] loadClassData(String name) {
        // If the custom path is not empty, set the custom path name
        if (path != null) {
            // Gets the class name at the end of the full path
            name = path + name.substring(name.lastIndexOf(".") + 1) + ".class";
        } else {
            name = splitDot("out.production.MyProject_02_arithmetic." + name) + ".class";
        }
        FileInputStream inputStream = null;
        ByteOutputStream outputStream = null;
        byte[] res = null;
        try {
            // Get file data from file input stream
            inputStream = new FileInputStream(new File(name));
            // Get output stream
            outputStream = new ByteOutputStream();
            // Create buffer
            byte[] buf = new byte[2];
            int len = -1;
            // Loop outputs the buffer to the output stream
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
            // Returns an array of output stream bytes
            res =  outputStream.toByteArray();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (inputStream != null) inputStream.close();
                if (outputStream != null) outputStream.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    // Set "." Replace with "/"
    private String splitDot(String s) {
        return s.replace(".", "/");
    }

    public static void main(String[] args) throws Exception {
        Main1 main1 = new Main1();
        // Custom classpath, D: / MyClass class
        main1.path = "D:/";
        Class<?> myClass = main1.loadClass("org.gxuwz.arithmatic.lanqiao.MyClass");
        System.out.println(myClass.getClassLoader());
    }
}

Output custom loader: org gxuwz. arithmatic. lanqiao. Main1@45ee12a7

Custom loader process:

loadClass() -> findClass() -> loadClassData()

  • In the startup class, call loadClass() through the custom loader.
  • loadClass() and then call the custom method findClass().
  • findClass() and then call loadClassData().

Loader conclusion:

  • The class loader will only load the same class once (in the same location).
  • First entrust AppClassLoader to load. AppClassLoader will look for whether it exists in the classpath path. If it exists, it will be loaded directly.
  • Otherwise, it is possible (it may also be handed over to the extension and root loader) to be loaded by the custom loader.
  • In the parent delegation system, the lower level loaders refer to the upper level parent loaders, and there is no inheritance relationship between the loaders.

loadClass source code analysis:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
            	// 1. If the parent loader is not empty, delegate the parent loader to load
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                	// 2. If the parent loader is empty, it indicates that the parent delegation has called the top-level loader (root loader)
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }
			// 3. If it is null, it means that the parent loader failed to load and can only be loaded by itself
            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

Advantages of parental delegation mechanism:

It can prevent the user-defined class and the class in rt.jar from having the same name and causing confusion.

The following code is to customize a Java LangMath class (same name as rt.jar in jdk):

package java.lang;

public class Math {
	public static void main(String[] args) {
		System.out.println("Math...");
	}
}

Operation results:

reason:
Because of the parent delegation mechanism, the higher the priority of the loader at the top level, and the root loader bootstrap is the highest level. If the priority is the highest, it will be loaded first. Therefore, java.jar in rt.jar is loaded Lang. Math class, which is not our custom Math class, so if there is no main method, an exception will be thrown.

Characteristics of parental delegation:

  • If there is an inheritance relationship: both sides of the inheritance (parent class and child class) must be the same loader, otherwise an error is reported.
  • If the loader of the custom class does not exist, the loader of the App class can access it (otherwise, the loader of the custom class cannot access it).

11. OSGi specification

OSGi features:

1. Reticular structure.
2. Shield the heterogeneity of hardware. For example, the project can be deployed on the network, and node B can be operated remotely on node a. In operation, it can be insensitive to hardware. The project on node B can also be operated and deployed on node A. ideally, there is no need to pause or restart during maintenance, which is supported naturally.

12. Class uninstallation

  • The system comes with (system loader, extension loader, root loader): the classes loaded by these loaders will not be unloaded.
  • The classes loaded by the user-defined loader will be unloaded by GC.

Configuring the loading and unloading parameters of the class will print the loading and unloading of the class, as follows:

-XX:+TraceClassLoading
-XX:+TraceClassUnloading

(1) The custom loader does not unload classes

Load the class file under disk D through the custom loader, then set it to null, call GC recycling, and check whether the loader unloads the class:

public class ClassLoaderUnLoading {
    public static void main(String[] args) throws Exception {
        // Custom loader
        MyClassLoader classLoader = new MyClassLoader();
        // Specify disk D files
        classLoader.path = "D:/";
        Class<?> aClass = classLoader.loadClass("com.vovhh.AClass");
        System.out.println("Loaded");
        aClass = null;
        classLoader = null;
        System.gc();
    }
}

The custom loader is unloaded after GC, and the output results are as follows:

(2) The system's own loader will not unload classes

Load classes using system loader:

public class ClassLoaderUnLoading {
    public static void main(String[] args) throws Exception {
        // Custom loader
        MyClassLoader classLoader = new MyClassLoader();
        // Specify disk D files
        Class<?> aClass = classLoader.loadClass("com.vovhh.AClass");
        System.out.println("Loaded:" + aClass.getClassLoader());
        aClass = null;
        classLoader = null;
        System.gc();
    }
}

The system's own loader will not unload classes, and the output results are as follows:

13. JVM detection tool

(1) jsp: view the java process (Java command, in jdk/bin directory).
Command: jps

(2) jstat: you can only view the memory of the current time, the memory of the new generation, the old generation and other areas.
Command: jstat -gcutil jps process number

(3) jmap: View heap memory usage.
Command: jmap -heap jps process number
(4) jconsole: a graphical interface to view memory usage.
Command: jconsole or jconsole jps process number
Select the corresponding process and click Connect:

View memory:

Switch to the "memory" interface and click "execute gc" in the upper right corner. It is found that there is little memory recovered by gc, indicating that there are problems in the current process and need to be optimized.

(5) jvisualvm: visual tool (which entity can be viewed).
Commands: jvisualvm
Steps: left class process - > monitor - > heap Dump (put memory information into hard disk) - > Find - > maximum object list
As follows:


(6) Through VM parameters: when the memory overflows, the heap memory information at the overflow time is automatically dumped.

-Xmx100m
-Xms100m
-XX:+HeapDumpOnOutOfMemoryError

Set the above parameters in VM: maximum memory, minimum memory and record heap memory overflow information.

After the heap memory overflows, it will Dump into the "java_pid12120.hprof" file (usually in the project root directory).

Load the above files through jvisualvm according to:

Follow the previous steps to check the memory usage of hprof files:

14. GC tuning

  1. Under the same known conditions, sacrifice low latency for high throughput, or vice versa.
  2. With the development of software and hardware, both may be improved.

Development history of GC

The JVM itself has made many improvements and upgrades on GC.
JVM default GC: CMS GC - > G1 GC (jdk9) - > ZGC (jdk11)

  • Serial GC:
    Serial GC is a serial collector (single thread) in a single core environment. When GC is recycled, other threads must wait and are generally not used.
  • Parallel GC:
    Based on Serial, multithreading technology is used to improve the throughput.
  • CMS GC:
    CMS uses multithreading technology and "mark clear" algorithm, which can greatly improve the efficiency (especially in low latency). jdk9 was gradually abandoned after, due to cumbersome configuration, many parameters, high requirements for developer experience, and more fragments.
  • G1 GC:
    jdk9 starts to be used by default. Features: the heap memory will be divided into many regoins of equal size, and the status of these areas will be marked, which is convenient to quickly locate idle regoins during GC. It is dedicated to GC region s with garbage, which greatly improves the efficiency of GC. G1 adopts the "mark sort" algorithm.
  • Z GC:
    jdk11 starts to provide a new GC to recycle TB level garbage in the range of milliseconds.

case

If the detection tool finds that Minor GC and Full GC are recycling frequently, how to optimize?

  • Reasons for frequent recycling of Minor GC: too many objects in the new generation (trigger Minor GC) - > too many objects with short life cycle - > more objects escaping to the old age - > more new generation and more old generation (trigger Full GC).
  • We can try to enlarge the maximum space of the Cenozoic.
  • Increase the age at which the new generation is promoted to the old age, and reduce the probability of objects with short life cycle transferring to the old age.

Topics: Java