Chapter 2 JVM memory allocation and Chapter 2 jvm allocation
Note: This blog is mainly based on the following three books:
Distributed Java applications: basics and practices
Deep understanding of Java Virtual Machine (version 2)
16 lessons that break the basic skills of programmers
Note: For details about the JVM memory structure, refer to Chapter 1 JVM memory structure. The JVM memory allocation mentioned below mainly refers to the allocation of new objects in the heap memory under the Hotspot JVM.
1. Basic process of creating a real object
Step 5:
- Check the class loading mechanism
- JVM first checks whether the parameter of a new command can locate a symbolic reference in the constant pool, check whether the class referenced by this symbol has been loaded, parsed, and initialized (in fact, check whether the class to which the new object belongs has executed the class loading mechanism ). If not, load the class by the class loading mechanism first. Next, let's talk about the class loading mechanism.
- Allocate memory
- Divides memory of a fixed size from the Java heap.
- Initialize the zero value (Operation instance data part-one of three parts of the Object Memory layout)
- You can directly use the default zero value for the instance field of the object without assigning an initial value.
- Each type of object has a different default zero value.
- Set the object header (Operation object header part-one of three parts of the Object Memory layout)
- See Object Memory layout appendix Java object memory Layout
- Run <init>
- Assign a value to the field of the object (in step 3, only the zero value is initialized. Here, the value is assigned to the instance based on the program written)
2. Concept of Memory Allocation
- After the class is loaded, the memory size required for an object can be completely determined. For details, see the memory layout of the object.
- Allocate space for the object, that is, divide the memory of the object determined by the size (the size of the Object Memory determined above) from the Java heap.
3. Two Methods of Memory Allocation
- Pointer collision
- Applicable scenarios: When the heap memory is regular (no memory fragments)
- Principle: All used memory is integrated to one side, and unused memory is placed on the other side. There is a demarcation value pointer in the middle, you only need to move the pointer to the memory size position of the object in the direction of unused memory.
- Gc collector: Serial, ParNew
- Idle list
- Applicable scenarios: When the heap memory is irregular
- Principle: The virtual Opportunity maintains a list of available memory blocks, find a large enough memory block to divide it into object instances (this is similar to the slab model of memcached), and finally update the list records. For introduction to memcached slab Memory Model, see Chapter 6 memcached Analysis
- Gc collector: CMS
- Note:
- Which of the above two methods depends on whether the Java heap memory is regular
- Whether the Java heap memory is regular depends on whether the GC collector algorithm is "mark-clear" or "mark-sort" (also known as "mark-compress ")
4. Memory Allocation concurrency Problems
Heap memory is the shared area of each thread. Therefore, when operating the heap memory, you need to handle concurrency issues. There are two processing methods:
- CAS + retry upon failure
- The specific method is similar to the implementation of the getAndSet (int newValue) method of AtomicInteger. For the source code parsing of AtomicInteger, see Chapter 1 AtomicInteger source code parsing.
- TLAB (Thread Local Allocation Buffer)
- Principle: allocate a piece of memory to each thread in advance in the Eden area. When JVM allocates memory to the objects in the thread, it first allocates memory in the TLAB, when the remaining memory of the object is larger than that in TLAB or the memory of TLAB is exhausted, the CAS is used for memory allocation.
- -XX: +/-UseTLAB: whether to use TLAB
- -XX: TLABWasteTargetPercent: Set the ratio of Eden zones that TLAB can occupy. The default value is 1%.
- JVM assigns a TLAB of the proper size to each thread based on the following three conditions:
- -XX: TLABWasteTargetPercent
- Number of threads
- Is the thread frequently allocating objects?
- -XX: PrintTLAB: View TLAB usage
5. Summary
- Create as few objects as possible
- According to the first part, the process of creating an object is complex and time-consuming.
- Fewer objects are created, and less garbage will be collected by the garbage collector in the future, improving efficiency.
- If you create fewer objects and consume less memory, the remaining system memory will be relatively large and the system will run faster.
- Avoid creating objects in frequently used methods or in cycles
- Multiple small objects are more efficient than large objects.
- This is based on TLAB. Multiple small objects can allocate memory in their respective TLAB in parallel. For large objects, the memory can only be allocated through CAS synchronization.
- Measure the preceding two points
- For String
- Try to use direct quantity: eg. string str = "hello"; // constants directly exist in the "constant pool", rather than String str = new String ("hello "); // In addition to "hello" in the "constant pool", a char []
- Do not concatenate strings with strings. Many temporary strings are formed: String s1 = "hello1"; String s2 = "hello2"; String s3 = "hello3 "; string s4 = s1 + s2 + s3;View Code
In fact, we only want the string s1 + s2 + s3, but in the above splicing process, a temporary string of s1 + s2 will be formed. Concatenate a string using StringBuilder. This class is better than StringBuffer because it is not a synchronization class.
- Release reference of useless objects as soon as possible (help garbage collection) public void info () {Object obj = new Object (); System. out. println (obj. hashCode (); obj = null; // explicitly release useless objects}View Code
As shown in the preceding method, the obj is a local variable. After the method is executed, the stack frame will go out of the stack and be recycled, the local variables stored in the stack frame are recycled together, so the "obj = null;" here is useless, but see below
Public void info () {Object obj = new Object (); System. out. println (obj. hashCode (); obj = null; // explicitly release useless objects // There are some time-consuming and memory-consuming operations below. These operations are irrelevant to obj}View CodeAt this time, if we add the "obj = null;" sentence, it is possible that the obj will be recycled before the method execution ends.
- Use as few static variables as possible. Because static variables are class variables and stored in the method area, the occupied memory cannot be recycled by the garbage collector unless the class to which static variables belong is detached.
- Common objects are stored in the cache or connection pool (in fact, the connection pool can also be regarded as a cache)
- Use SoftReference (I will talk about several reference methods later)
- When the memory is sufficient, the function is equivalent to a common variable.
- When the memory is insufficient, release the objects referenced by the soft reference.
- It is generally used for large arrays and large objects.
- The object obtained through soft reference may be null (when the memory is insufficient, release the object referenced by soft reference). In the application, you need to check whether the object is null. If it is null, objects to be rebuilt