Write in front:
Hello, everyone! Today we are going to learn about Java virtual machine, as a must-ask knowledge point in the interview, to understand a wave of in-depth!
Mind mapping:
1. What is a JVM?
Summary of 1.1,
The JVM is short for Java Virtual Machine, a specification for computing devices. With the introduction of the Java Virtual Machine, the Java language does not need to be recompiled when running on different platforms. Java language compilers can run unchanged on multiple platforms simply by generating object code (bytecode) that runs on the Java virtual machine. Bytecode files (.class) can run on any platform that has a Java virtual machine specific to that platform. This is “compile once, run many times”.
So-called Java can realize cross-platform, is by the virtual machine to run different on different platforms, so the execution of Java files are not directly on the operating system, but by the JVM virtual machine implementation, we can see from this picture, the JVM does not deal directly with hardware, but interact with the operating system to implement a Java program.
1.2. The JVM runs the process
Here is the composition diagram of the JVM, which consists of four parts:
-
Class loader
The purpose of the class loader is to load the class file into memory. For example, if we execute a.java program file, first use the javac command to compile and generate a.class file. We then need to use the class loader to load the bytecode file into memory and use subsequent modules of the JVM to load the executable. Whether it can be executed is up to the execution engine.
-
Execution engine
Execution engines, also called interpreters, interpret commands and submit them to the operating system for execution.
-
Local interface
Its purpose is to fuse different programming languages for Java, an approach that is increasingly being used today, except in hardware-related applications, such as using Java programs to drive printers, or Java systems to manage production equipment.
-
Runtime data area
The running data area is the focus of the entire JVM. Everything we write is loaded here before it runs, and the Java ecosystem thrives because of the region’s autonomy. The entire JVM framework is loaded by the loader, which then processes the data in memory and needs to interact with heterogeneous systems via a local interface!
2. the memory region of the JVM
The memory area is the run-time data area above. Programmers working in C or C++ must be responsible for the entire life cycle of each object. But for Java programmers, there is no need to write delete or free code for every object under the JVM’s automatic memory management mechanism, which makes memory leaks and memory spills less likely. But because Java programmers have delegated the power of memory management to the memory management mechanism, it can be a complex and difficult task to troubleshoot a memory leak or overflow problem without a clear understanding of the JVM’s memory structure.
Runtime data area
2.1. Program calculator
A program counter is a small area of memory that can be regarded as an indicator of the line number of the bytecode executed by the current thread. In the conceptual model of the virtual machine, bytecode interpretation works by changing the value of the program counter to select the next bytecode instruction to execute. Functions such as branch control, loop control, jump, exception operations, thread recovery and so on are done through this counter.
Since JVM multithreading is implemented by switching threads in turn and allocating processor execution time. Thus, at any given moment, a processor (or a kernel for multi-core processors) will execute instructions in only one thread. Therefore, in order to return to the correct execution position after thread switch, each thread needs its own unique program counter, which does not affect each other and is stored independently. We call this type of memory area thread-private memory area.
If the thread executes a Java method, the program counter records the address of the bytecode instruction that the Java VIRTUAL machine is executing, while when the thread executes a Native method, the program counter is empty, because at this time, the Java VIRTUAL machine calls the interface related to the operating system, and the implementation of the interface is not Java language. It’s C and C++.
The program counter is the only memory area in the Java Virtual machine where outofMemoryErrors do not occur, and its life cycle is created with the creation of a thread and ends with the completion of the thread.
2.2. Java Virtual Machine stack
Like the program counter, the Java virtual machine stack is thread-private and has the same life cycle as the thread. The virtual machine stack describes the execution memory model of Java methods. Each method creates a stack frame (used to store information about local variables, operand stack, dynamic chain stack, method exit, etc.) during execution. The process from execution to completion of each method corresponds to the process of a stack frame from the stack to the stack.
Java memory can be roughly divided into Heap memory and Stack memory, but the division of Java memory areas is actually much more complicated than that, and what we now call the Java virtual machine Stack is the Stack memory here, or the local variable scale part of the virtual machine Stack.
The local variable table contains the four basic data types known by the compiler (Boolean, byte, CHAR, short, int, float, long, double), and the object reference type (which, unlike the object itself, may be a reference pointer to the object’s starting address). It may also point to a handle representing an object or other location associated with this object.
The Java virtual machine has two exceptions:
A StackOverFlowError occurs if the thread requests more depth in the stack than the virtual machine allows. OutOfMemoryError is thrown if the virtual stack can scale dynamically and the extension cannot allocate sufficient memory.
2.3. Local method stack
The function of the local method stack is very similar to that of the virtual machine stack, except that the virtual machine stack performs Java methods (i.e. bytecode) services for the virtual machine, while the local method stack serves Native methods used by the virtual machine. In the HotSpot VIRTUAL machine, the virtual machine stack and the local method stack are directly combined.
Like the Java virtual machine stack, the local method stack creates a stack frame (used to store information about the local variator, operand stack, dynamic chain stack, method exit, and so on) during execution. StackOverFlowError and OutOfMemoryError are also thrown.
2.4, the Java heap
The Java heap is the largest area of memory managed by the JVM. The Java heap is an area shared by all threads and created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and almost all object instances and arrays are allocated memory here.
The Java Heap is the primary area managed by the Garbage collector and is therefore also known as the Garbage Collected Heap. From a memory collection point of view, the Java heap can also be subdivided into the new generation and the old generation, since collectors are now mostly generational garbage collection algorithms. ** The purpose of further partitioning is to better reclaim memory, or to allocate memory faster. ** According to the SPECIFICATION of the JVM, the Java heap can be in a physically discontinuous memory space as long as it is logically contiguous. OutOfMemoryError is thrown if memory allocation has not been completed in the heap and the heap has no expandable memory space.
2.5. Method area
The method area, like the Java heap, is an area of memory shared by individual threads to store data such as class information that has been loaded by the virtual machine, constants, static variables, code compiled by the just-in-time compiler, and so on. Although the Java Virtual Machine specification describes the method area as a logical part of the Heap, it has an alias called non-heap, which is supposed to distinguish it from the Java Heap.
Java virtual machines have relatively loose limits on method areas, in addition to the fact that, like the heap, they don’t require contiguous space and can choose to be fixed size or extensible, they can also choose not to implement garbage collection. Relatively speaking, garbage collection is relatively rare in this area, but it is not possible for data to live forever after entering the method area. The collection goal of this area is mainly the collection of constant pool and the unloading of types. Generally speaking, the collection performance of this area is not satisfactory. Especially the type of unloading, the conditions are quite harsh. According to the Java Virtual Machine specification, OutOfMemoryError is thrown when the method area cannot meet the memory allocation.
Let’s use a simple example here to see which of the above information is stored in the method area;
Static variables and constants are placed in the method area at compile time;
// Static variables stored in the method area during compilation
private static int num=10;
// Constant stored in the method area during compilation
private final String name="boy";
Copy the code
Let’s first look at what happens in the heap when we have a new String;
String s1="hello";
String s2=new String("hello");
String s3=new String("hello");
System.out.println(s1==s3); // false
System.out.println(s2==s3); // false
Copy the code
The result of this output must be false. When new is used, it creates a block of heap memory to store the hello object. S2 and S3 point to the same content, but the stack address is different, so it is not equal.
For reference types, “==” refers to a comparison of address values.
Double-quoted strings are in the constant pool, while new objects are not.
Let’s look at what was added to the constant pool at runtime;
String s2=new String("hello");
String s3=new String("hello");
// Add to the constant pool at run time
System.out.println(s2.intern()==s3.intern());
Copy the code
If the current string exists in the constant pool, a reference to the object in the constant pool is returned.
If the string is not in the constant pool, the string reference is saved to the constant pool and then returned directly!
2.6, run-time constant pooling
The runtime constant pool is part of the method area. In addition to the Class version, field, method, interface, and other description information, the Class file also contains constant pool information (used to store various literal and symbolic references generated at compile time). Since the constant pool is part of the method area at runtime and is naturally limited by the method area memory, OutOfMemoryError is thrown when the constant pool can no longer claim memory.
2.7. Direct memory
Direct memory is not part of the Jvm runtime data area, but it is frequently called and may cause OutofMemoryErrors. Obviously native direct memory is not affected by Java heap allocated memory, but since it is memory, it is certainly limited by the total native memory size and processor addressing space. When configuring VM parameters, the server administrator sets parameters such as -xmx based on the actual memory, but often ignores the direct memory. The total memory of each region is greater than the physical memory limit, resulting in OutOfMemoryError during dynamic expansion.
3. Java object creation process
The following diagram shows the Java object creation process, which is divided into five parts.
3.1. Class loading process
When a virtual machine arrives at a new instruction, it first checks to see if the instruction’s arguments locate the symbolic reference to the class in the constant pool, and to see if the symbolic reference represents a class that has been loaded, parsed, and initialized. If not, the corresponding class loading process must be performed first.
3.2. Allocate memory
After the class load check passes, the virtual machine next allocates memory for the new objects. The size of memory required by an object is determined after the class is loaded, and the task of allocating space for an object is equivalent to dividing a certain size of memory from the Java heap. There are two allocation methods: “pointer collision” and “free list”, which are determined by the cleanliness of the Java heap, which in turn is determined by the use of the garbage collector with collation capabilities.
Pointer collision:
- Scenario: Memory in the Java heap is absolutely tidy;
- Principle: All used memory is placed on one side, free memory is placed on the other side, a pointer is placed in the middle as a demarcation point indicator, allocation of memory only need to move that pointer to the free space of a distance equal to the size of the object;
- GC collectors: Serial, ParNew, and other collectors with Compact procedures.
Free list:
- Scenario: Memory in the Java heap is not tidy;
- How it works: The vm maintains a list of available memory blocks, finds a large enough space in the list to allocate to object instances, and updates the list.
- GC collector: CMS collector based on the Mark-sweep algorithm.
Concurrent memory allocation problems
Another consideration when creating objects is whether threads are safe in the case of concurrency. Because object creation is A very frequent activity in virtual machines, it is possible that object A is allocating memory, and object B uses the original pointer to allocate memory at the same time. Therefore, thread safety must be ensured. There are two solutions to this problem:
- **CAS and retry failures (compare and swap) : ** Synchronization of memory allocation operations — virtual machines actually use CAS and retry failures to ensure atomicity of update operations. The CAS operation requires input of two values, an old value (the expected value before the operation) and a new value. During the operation, the old value is compared to see if there is any change. If there is no change, the new value is exchanged.
- **TLAB (Allocation buffer) : ** Allocates memory in a separate space according to the thread, i.e. each thread allocates a small chunk of private memory in the Java heap, i.e. the local thread allocation buffer. The goal of TLAB is to allow each Java application thread to use its own dedicated allocation pointer to allocate memory for new objects, reducing synchronization overhead.
3.3. Initialize zero
After the memory allocation is complete, the VIRTUAL machine needs to initialize the allocated memory space to zero values (excluding the object header). This step ensures that the instance fields of the object can be used in Java code without assigning initial values, and the program can access the zero values corresponding to the data types of these fields.
3.4. Set the object header
After initializing the zero value, the virtual machine sets up the object as necessary, such as which class the object is an instance of, how to find the metadata information about the class, the object’s hash, the object’s GC generation age, and so on. This information is stored in the object header. In addition, the object header can be set differently depending on the running status of the VM, for example, whether biased locking is enabled.
3.5. Execute Init
From the virtual machine’s point of view, a new object has been created, but from the Java program’s point of view, object creation has just begun, the
method has not yet been executed, and all fields are still zero. So, in general, the new instruction is followed by the
method, which initializes the object as the programmer wishes, and a usable object is fully generated.
4. Object access positioning
Objects are created to use objects, and our Java program operates on specific objects on the heap using reference data on the stack. Object access methods are determined by virtual machines. Currently, the mainstream access methods are handle and direct pointer.
4.1. Use handles
If handles are used, the Java heap will allocate a chunk of memory as a handle pool. Reference stores the handle address of the object, and the handle contains the specific address information of the instance data and the type data respectively. As shown in the figure:
4.2. Direct Pointers
If direct pointer access is used, then the layout of the Java heap object must consider how to place information about the access type data, and the direct stored in Reference is the address of the object. As shown in the figure:
** The biggest advantage of using a handle to access objects is that reference stores a stable handle address. ** Only changes the instance data pointer in the handle when the object is moved, and reference itself does not need to be modified. ** The main advantage of using direct pointer access is that it is faster. ** It saves time for a pointer location. Because object access is so frequent in Java, this kind of overhead can add up to a very optimistic execution cost.
5. OutOfMemoryError(memory overflow) exception
In addition to the program calculator, several other runtime areas of ** virtual machine memory are described by the Java Virtual Machine specification as having the potential for OutOfMemoryError exceptions. ** Now we’ll use two examples to verify the scenarios where exceptions occur, as well as a preliminary introduction to some of the most basic memory-related virtual machine parameters.
5.1, heap memory exception
Let’s demonstrate the heap memory exception:
/ * *
* @authorPublic id: Programmer's time
* @createThe 2020-11-23 08:54
* @description
* /
public class HeapOOM {
public static void main(String[] args) {
// Test heap memory exception
List<HeapOOM> heapOOMList=new ArrayList<>();
// Add only one object, no exception
heapOOMList.add(new HeapOOM());
// Add to an endless loop, constantly new objects, heap memory is exhausted
while (true) {
heapOOMList.add(new HeapOOM());
}
}
}
Copy the code
Before running this program, we need to set the Java virtual machine parameters. Since the heap memory of IDEA is large by default, we need a single configuration; Click Run >> Edit Configurations and then configure, as follows, initialize both the heap and Max heap at 10m to see if the above infinite loop can be completed in 10M;
Let’s look at the results:
As you can see, the heap memory is abnormal. In the infinite loop above, we are constantly new objects, so that the heap memory is exhausted and cannot allocate memory for new objects, which causes the exception.
5.2. Stack memory is abnormal
Let’s look at stack memory exceptions:
/ * *
* @authorPublic id: Programmer's time
* @create 2020-11-23 09:14
* @description
* /
public class StackOOM {
public static void main(String[] args) {
test();
}
// We set up a simple recursive method, without breaking out of the recursive condition, stack memory exception will occur
public static void test(a){
test();
}
}
Copy the code
We set up a simple recursive method, but do not give the condition to escape recursion, so it will be different.
The running results are as follows:
A StackOverflowError is raised when the stack depth of a thread request exceeds the maximum depth allowed by the virtual machine because of improper recursion.
Let’s look at the second anomaly:
/ * *
* @authorPublic id: Programmer's time
* @createThe 2020-11-23 10:05
* @description
* /
public class StackOOM1 {
// Thread tasks, each thread task is always executing
private void WinStop(a){
while(true) {
System.out.println(System.currentTimeMillis());
}
}
// keep creating threads
public void StackByThread(a){
while(true) {
Thread thread=new Thread(new Runnable() {
@Override
public void run(a) {
WinStop();
}
});
}
}
public static void main(String[] args) {
StackOOM1 stackOOM1=new StackOOM1();
stackOOM1.StackByThread();
}
}
Copy the code
The operation result code theory is: the Exception in the thread “is the main” Java. Lang. OutOfMemoryError: Unable to create new native thread, however, running this code may cause the operating system to stall, so it should be run with caution.
An OutOfMemoryError is raised when the virtual machine fails to allocate enough memory while extending the stack. This is caused by the continuous creation of active threads.
Wechat search public number “programmer’s time” well, today is the first to share here, next time to continue to bring you JVM garbage collection interview content! More dry goods, quality articles, welcome to pay attention to my original technology public number ~
References:
An in-depth understanding of the Java Virtual Machine (2nd edition). Zhou Zhiming