JVM Basics

1. JVM runtime memory structure

1. Basic constitution of JVM

1.1 JVM Architecture Description (based on JDK1.8)

1.2 What is the JVM

JDK = JVM + SDK, JVM is the Java runtime environment. The JVM will encounter OOM memory overflow problems. Out of Memery is usually a heap memory overflow. The solution: properly set the JVM memory space.

1.3 Class loader – Class loader

Functions: Functions: The class loader is used to load Java classes to a Java VM.

In general, Java virtual machines use Java classes as follows: Java source programs (.java files) are converted to Java bytecode (.class files) after being compiled by the Java compiler. The classloader is responsible for reading the Java bytecode and converting it into an instance of the java.lang.Class Class. Each such instance is used to represent a Java class. An object of this class is created using the newInstance() method of this instance.

ClassLoader:

  • Bootstrap ClassLoader: Bootstrap ClassLoader. Written by C++ and started by the JVM, the lowest level class loader.

    Rt. jar, resources. Jar, charsets. Jar, and class files in %JRE_HOME/lib/

  • Extension ClassLoader: Extension ClassLoader. Java class, inherited from URLClassLoader.

    Responsible for loading the JDK’s own extension classes. The corresponding files are jar and class in %JRE_HOME/lib/ext, etc

  • App ClassLoader: ** Application loader. **Java class, inherited from URLClassLoader system class loader,

    The payload loads Java code written by itself. The corresponding files are all jars, classes, and so on in the application’s classpath directory

  • Custom loader: You can customize the loader.

1.4 ClassLoader loading mechanism – Parent delegation mechanism

  • What is the parent delegate mechanism

When a ClassLoader tries to load a class, it delegates its parent to try loading the class and up, and if the top-level parent doesn’t find the class, the delegate goes to the specific place to load the class.

// Java implementation source code
protectedClass<? > loadClass(String name,boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) { // First, check to see if it has been loadedClass<? > c = findLoadedClass(name);if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if(parent ! =null) { // if the parent loader is not empty, the parent loader loadClass is called
                        c = parent.loadClass(name, false);
                    } else { // If the parent loader is empty, Bootstrap Classloader is calledc = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader 
                }
                if (c == null) { // If still not found, then invoke findClass in order // to find the class. 
                    long t1 = System.nanoTime(); // If the parent loader is not found, call findClass
                    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) { / / call resolveClass ()
                resolveClass(c);
            }
            returnc; }}Copy the code
  • What the parent delegate mechanism does:

    1. Avoid loading the same. Class repeatedly. You can ask the delegate up there, so once it’s loaded, you don’t have to load it again. Ensure data security.

    2. Ensure that core.class cannot be tampered with. By delegating, you don’t tamper with the core.class, and if you do, you don’t load it, and if you load it, it won’t be the same.class object. Different loaders do not load the same.class object. This ensures Class execution security.

1.5 Garbage collection system

Role: Responsible for garbage collection, destruction, recycling memory. Garbage collection for Java heap, method area, and direct memory.

1.6 Execution Engine

Function: Executes compiled bytecode instructions.

The main execution techniques include interpretation execution, just-in-time compilation execution, adaptive optimization execution and direct execution on chip level

(1) Explanation: Belongs to the first generation JVM;

(2) Just-in-time compilation: JIT is a second-generation JVM;

(3) Adaptive optimization: at present, Sun’s HotspotJVM adopts this technique) by absorbing the experience of the first generation JVM and the second generation JVM and combining the two. Start by interpreting and monitoring all code execution, then start a background thread for frequently invoked methods, compile them into native code, and carefully optimize them. If the method is no longer used frequently, the compiled code is cancelled and interpreted.

(4) Chip-level direct execution: embedded in the chip, using local methods to execute Java bytecode. Android software development uses this approach.

Thread private area

  • Java stack

What it does: A thread is private and has the same lifetime as a thread. Store local variables, dynamic links, method exits, and more. The internal structure of a stack

  • Local method stack

Purpose: For Native method calls, JDK source code uses a lot of Native keywords, that is, to call the underlying C language written method.

Note: the (Sun HotSpot VIRTUAL machine) directly combines the local method stack with the Java stack.

  • PC register (program counter)

Action: A PC register is created when each thread is started. Saves the address of the next instruction to be executed.

3. Thread sharing area

  • Methods area

What it does: Like the heap, the Java method area is an area of memory shared by all threads that holds information about the system’s classes. Such as class fields, methods, constant pools, and so on. The size of the method area determines how many classes the system can hold. If the system defines too many classes, the method area overflows. Virtual machines can also throw memory overflow errors.

  • The Java heap

Purpose: Heap memory is used to hold objects and arrays created by new.

Creates an array or object in the heap, can also be defined in the stack, a special variable value of this variable is equal to the array or object in the heap memory address, in this particular variable in the stack becomes an array or object reference variables, it can be used in the program after stack memory references in the variable to access in the heap array or object, A reference variable is equivalent to an alias or code name for an array or object

  • The interrelationship between heap, method area, and stack

  • Direct memory

Role: Improves performance in some scenarios.

Direct memory is not part of the runtime data portion of the JVM virtual machine. NIO(New Input/Output) class is added in JDK1.4, introducing a Channel and Buffer based I/O mode, which can use the native function library to allocate out-of-heap memory directly. It then operates through a DirectByteBuffer object stored in the Java heap as a reference to this memory. This can significantly improve performance in some scenarios because it avoids copying data back and forth between the Java heap and Native heap.

The allocation of native direct memory is not limited by the Java heap size, but by the total native memory size

Do not ignore direct memory when configuring VM parameters to prevent OutOfMemoryError

  • Direct memory (off-heap memory) compared to heap memory

The performance of direct memory I/O is better than that of ordinary heap memory, but the difference is obvious in the case of multiple read/write operations

4. Internal structure of the heap



JDK8Begin to cancel the permanent generation and replace it with a metadata area that is not in the heap but is a direct memory outside the heap.

4.1 Process of garbage collection

Depending on the garbage collection mechanism, the Java heap may have different structures, most commonly dividing the entire Java heap into new generation and old generation. Among them, the new generation stores the new objects or young objects, and the old age stores the old objects.

The Cenozoic era is divided into den, S0 and S1. S0 and S1 are also known as from and to regions. They are two Spaces of equal size and can change roles with each other.

In most cases, objects are first allocated in Eden area. After Cenozoic recycling, if the object is still alive, it will enter S0 or S1 area. After each Cenozoic recycling, if the object is alive, its age will increase by 1.

5. Internal structure of stack

What it does: A thread is private and has the same lifetime as a thread. Store local variables, dynamic links, method exits, and more.

The stack holds the original value of the base type and the address value of the reference type.

Basic types include: byte, short, int, long, char, and float, double, Boolean, returnAddress reference types include class type, interface type and array.

The internal structure of the stack is as follows:

The stack is composed of a stack frame, and the structure in the stack frame is composed of local variable table, operand stack and frame data area.

Local variable table: Saves function parameters, local variables (the current function is valid, it is destroyed at the end of the function execution)

Operand stack: intermediate operation results, temporary storage space

Frame data area: save access constant pool pointer, exception handling table

2. JVM object model

Java is an object-oriented language, and the storage of Java objects in the JVM has a certain structure. This storage model of Java objects themselves is called the Java Object Model.

An Oop-Klass Model was designed in the HotSpot VIRTUAL machine (the most widely used Java virtual machine in the Sun JDK and OpenJDK). OOP (Ordinary Object Pointer) refers to a Pointer to a common Object, whereas Klass describes the specific type of Object instance.

For each Java class, when it is loaded by the JVM, the JVM creates an instanceKlass object for that class, which is stored in the methods area and used to represent the Java class at the JVM layer. When we create an object using new in Java code, the JVM creates an instanceOopDesc object that contains the object header and instance data.

3. Start tuning heap parameters

Take JDK1.8+HotSpot as an example

Jdk1.7:

Jdk1.8:

3.1. Common JVM parameters

How do I tune the JVM? Setting Parameters

parameter note
-Xms Initial heap size. The size of the heap used as soon as it is started, the default is 1/64 of memory
-Xmx Maximum heap size. The default is 1/4 of memory
-Xmn New area heap size
-XX:+PrintGCDetails Print verbose GC processing logs
-XX:MaxMetaspaceSize=128m Set the size of the meta-space – method area (template area) for example, 128 MB

The Java code looks at the default JVM heap size:

Runtime.getruntime ().maxMemory() // The maximum size of the heap. The default value is 1/4 of memory

3.2. How do I set JVM parameters

The running mode of IDEA is as follows:

3.3. View heap memory details

Public class Demo2 {public static void main(String[] args) {system.out.print (" Max heap size: "); Println (Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); system.out.println (Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); System.out.print(" current heap size: "); Println (Runtime.geTruntime ().totalMemory() / 1024.0/1024 + "M"); system.out.println (Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); System.out.println("=================================================="); byte[] b = null; for (int i = 0; i < 10; i++) { b = new byte[1 * 1024 * 1024]; }}}Copy the code

-XMX50m -xMS30m -xx :+PrintGCDetails

Execute: The following information is displayed

The sum of heap sizes for the new and old generations is Runtime.getruntime ().totalMemory().

3.4. The GC demonstration

public class HeapDemo { public static void main(String args[]) { System.out.println("=====================Begin========================="); System.out.print(" Max heap size: Xmx="); Println (Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); system.out.println (Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); System.out.print(" Free mem="); System.out.println(Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); System.out.print(" Current heap size: total mem="); Println (Runtime.geTruntime ().totalMemory() / 1024.0/1024 + "M"); system.out.println (Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); System.out.println("==================First Allocated==================="); byte[] b1 = new byte[5 * 1024 * 1024]; System.out.println("5MB array allocated"); System.out.print(" Free mem="); System.out.println(Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); System.out.print(" Current heap size: total mem="); Println (Runtime.geTruntime ().totalMemory() / 1024.0/1024 + "M"); system.out.println (Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); System.out.println("=================Second Allocated==================="); byte[] b2 = new byte[10 * 1024 * 1024]; System.out.println("10MB array allocated"); System.out.print(" Free mem="); System.out.println(Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); System.out.print(" Current heap size: total mem="); Println (Runtime.geTruntime ().totalMemory() / 1024.0/1024 + "M"); system.out.println (Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); System.out.println("=====================OOM========================="); System.out.println("OOM!!!" ); System.gc(); byte[] b3 = new byte[40 * 1024 * 1024]; }}Copy the code

JVM parameters set to maximum heap memory 100M, current heap memory 10M: -xmx100m -Xms10m -XX:+PrintGCDetails

Running again, you can see the Minor and Full GC logs:

3.5. OOM demonstration

Change the JVM parameters in the example above to 50M maximum heap memory and 10M current heap memory and run the test: -xmx50m-xMS10m

= = = = = = = = = = = = = = = = = = = = = Begin = = = = = = = = = = = = = = = = = = = = = = = = = maximum heap size: -xmx = 44.5 M surplus heap size: free mem = 8.186859130859375 M the current heap size: Total mem = 9.5 M = = = = = = = = = = = = = = = = = First Allocated = = = = = = = = = = = = = = = = = = = = = 5 MB array surplus Allocated heap size: Free mem= 3.1868438720703125m Total mem = 9.5 M = = = = = = = = = = = = = = = = Second Allocated = = = = = = = = = = = = = = = = = = = = 10 MB array surplus Allocated heap size: Free mem = 3.68682861328125 M the current heap size: total mem = 20.0 M = = = = = = = = = = = = = = = = = = = = = OOM = = = = = = = = = = = = = = = = = = = = = = = = = OOM!!!!!! Exception in thread “main” java.lang.OutOfMemoryError: Java heap space: Free mem=3.1868438720703125M Total mem = 9.5 M = = = = = = = = = = = = = = = = Second Allocated = = = = = = = = = = = = = = = = = = = = 10 MB array surplus Allocated heap size: Free mem = 3.68682861328125 M the current heap size: total mem = 20.0 M = = = = = = = = = = = = = = = = = = = = = OOM = = = = = = = = = = = = = = = = = = = = = = = = = OOM!!!!!! Exception in thread “main” java.lang.OutOfMemoryError: Java heap space at com.atguigu.demo.HeapDemo.main(HeapDemo.java:40)