On the virtual machine structure of Java and the optimization of virtual machine memory
Since working, the code has been written more and more, the program has become more and more bloated, and the efficiency has become lower and lower. For a programmer who pursues perfection, this is absolutely not allowed. Therefore, in addition to continuously optimizing the program structure, memory optimization and performance tuning have become my usual "tricks".
To optimize the memory and performance of Java programs, it is definitely not possible to not understand the internal principles of the virtual machine (or to be more rigorous in the specification). Here is a good book "going deep into the Java virtual machine (Second Edition)" (written by bill Venners and translated by Cao Xiaogang and Jiang Jing. In fact, the text is the author's personal understanding of the Java virtual machine after reading this book). Of course, the benefits of understanding the Java virtual machine are not limited to the above two benefits. From a deeper technical level, understanding the specification and implementation of Java virtual machine will help us write efficient and stable java code. For example, if we understand the memory model of the Java virtual machine and the memory recycling mechanism of the virtual machine, we will not rely too much on it, but will explicitly "release memory" when needed (Java code can not explicitly release memory, but can tell the garbage collector to recycle the object by releasing object reference), so as to reduce unnecessary memory consumption; If we understand the working principle of Java stack, we can reduce the risk of stack overflow by reducing the number of recursion layers and the number of cycles. Perhaps for application developers, they may not directly involve the underlying implementation of these Java virtual machines, but understanding these background knowledge will have a subtle and good impact on our programs.
This article will briefly explain the architecture and memory model of Java virtual machine. If useful words are inappropriate or inaccurate, please correct them. I am deeply honored!
Java virtual machine architecture
Class loading subsystem
There are two kinds of loaders for Java virtual machine, namely startup class loader and user-defined loader.
The general class loading subsystem uses the fully qualified name of the class (package name and class name, network loading also includes URL) load class into the runtime data area. For each loaded type, the Java virtual machine will create an instance of java.lang.class class to represent the type. The instance is placed in the heap area in memory, and the loaded type information is located in the method area, which is the same as all other objects.
Before loading a type, the class loading subsystem should not only locate and import the corresponding binary class file, but also verify the correctness of the imported class, allocate and initialize memory for class variables, and resolve symbol references to direct references. These actions are carried out in strict accordance with the following sequence:
1) Loading -- find and load binary data of type;
2) Connection - perform validation, preparation, and resolution (optional)
3) Verify that the imported type is correct
4) Prepare to allocate memory for class variables and initialize them to default values
5) Parsing converts symbolic references in types to direct applications
Method area
For each type loaded by the class loading subsystem, the virtual machine will save the following data to the method area:
1. Fully qualified name of type
2. Fully qualified name of type superclass (java.lang.object has no superclass)
3. Is the type class type or interface type
4. Access modifier of type
5. Ordered list of fully qualified names of any direct super interface
In addition to the above basic type information, the following information will be saved:
6. Constant pool of type 7 Field information (including field name, field type and field modifier) 8 Method information (including method name, return type, number and type of parameters, method modifier. If the method is not abstract and local, the bytecode, operand stack, size of local variable area and exception table in the method stack frame will also be saved) 9 All class variables other than constants (in fact, they are static variables of the class. Because static variables are shared by all instances and are directly related to types, they are class level variables and are saved in the method area as members of the class) 10 A reference to class classloader
Note that the method area can also be recycled by the garbage collector.
heap
All class instances or arrays created by a java program at runtime are placed in the same heap, and each Java virtual machine also has a heap space, and all threads share a heap (this is the reason why a multi-threaded Java program will have synchronization problems in object access).
Since each Java virtual machine has different implementations of virtual machine specifications, we may not know how each Java virtual machine represents object instances in the heap, but we can see the clue through the following possible implementations:
Program counter
For a running Java program, each thread has its own PC (program counter) register. It is created when the thread starts. The size is one word long, which is used to save the location of the next line of code to be executed.
Java stack
Each thread has a Java stack, which saves the running state of the thread in stack frames. There are two kinds of virtual machine operations on Java stack: pressing stack and out of stack, both of which have taken frame as unit. The stack frame saves data such as incoming parameters, local variables and intermediate operation results. It is popped up when the method is completed, and then released.
Take a look at the memory snapshot of the stack frame when two local variables are added
Native Method Stack
This is where Java calls the local library of the operating system to implement JNI (Java Native Interface)
Execution engine
The core of Java virtual machine, which controls the loading and parsing of Java bytecode; For running Java programs, each thread is an independent instance of the virtual machine execution engine. From the beginning to the end of the thread life cycle, it is either executing bytecode or executing local methods.
Local interface
It connects the local method stack and the operating system library.
Note: all references to "Java virtual machine" in this article refer to "Java virtual machine specification of Java EE and Java se platform".
Virtual machine memory optimization practice
Since we mention memory, we have to talk about memory leakage. As we all know, Java is developed from C + +, and a big problem of C + + programs is that memory leakage is difficult to solve. Although the Java JVM has its own garbage collection mechanism to recover memory, in many cases, it does not require too much attention from Java program developers, but there is also a leakage problem, which is only a little smaller than C + +. For example, if there is a referenced but useless object in the program: the program references the object, but it will not or can no longer use it, then the memory space it occupies is wasted.
Let's take a look at how GC works: monitor the running status of each object, including application, reference, referenced, assignment, etc. when the object is no longer referenced, release the object (GC is the focus of this article and will not elaborate too much). Many Java programmers rely too much on GC, but the key to the problem is that no matter how well the JVM garbage collection mechanism is done, memory is always a limited resource. Therefore, even if GC will complete most garbage collection for us, it is necessary to pay due attention to memory optimization in the coding process. This can effectively reduce the number of GC, improve the memory utilization and maximize the efficiency of the program.
Generally speaking, the memory optimization of Java virtual machine should start from two aspects: Java virtual machine and Java application. The former refers to controlling the size of the logical memory partition of the virtual machine through the virtual machine parameters according to the design of the application program, so as to make the memory of the virtual machine and the memory requirements of the program complement each other; The latter refers to optimizing program algorithm, reducing GC burden and improving GC recovery success rate.
The parameters for optimizing virtual machine memory through parameters are as follows:
Xms
Initial heap size
Xmx
Java heap Max
Xmn
Heap size of young generation
Xss
Stack size per thread
The above are three commonly used parameters, as well as some:
XX:MinHeapFreeRatio=40
Minimum percentage of heap free after GC to avoid expansion.
XX:MaxHeapFreeRatio=70
Maximum percentage of heap free after GC to avoid shrinking.
XX:NewRatio=2
Ratio of new/old generation sizes. [Sparc -client:8; x86 -server:8; x86 -client:12.]- client:8 (1.3.1+),x86:12]
XX:NewSize=2.125m
Default size of new generation (in bytes) [5.0 and newer: 64 bit VMs are scaled 30% larger; x86:1m; x86,5.0 and older: 640k]
XX:MaxNewSize=
Maximum size of new generation (in bytes). Since 1.4,MaxNewSize is computed as a function of NewRatio.
XX:SurvivorRatio=25
Ratio of eden/survivor space size [Solaris amd64: 6; Sparc in 1.3.1: 25; other Solaris platforms in 5.0 and earlier: 32]
XX:PermSize=
Initial size of permanent generation
XX:MaxPermSize=64m
Size of the Permanent Generation. [5.0 and newer: 64 bit VMs are scaled 30% larger; 1.4 amd64: 96m; 1.3.1 -client: 32m.]
The following is to improve memory utilization and reduce memory risk by optimizing program algorithms. It is purely empirical and for reference only. If there is anything wrong, please correct it. Thank you!
1. Release the reference of useless object as soon as possible (XX = null;)
Look at a piece of code:
2. Carefully use collection data types, such as array, tree, graph, linked list and other data structures, which are more complex for GC.
3. Avoid explicitly applying for array space. When you have to explicitly apply, try to accurately estimate its reasonable value.
4. Try to avoid creating and initializing a large number of objects in the default constructor of the class, so as to prevent unnecessary waste of memory resources when calling the constructor of its own class
5. Try to avoid forcing the system to recycle garbage memory and increase the final time for the system to recycle garbage
6. Try to use the instantaneous value variable in the application development of remote method call class, unless the remote caller needs to obtain the value of the instantaneous value variable.
7. Try to use object pool technology in appropriate scenarios to improve system performance