1. An overview of the

For Java programmers, under the automatic memory management mechanism of virtual machine, there is no need to write corresponding DELETE /free operation for a new operation like C/C++ program developers, which is not prone to memory leakage and overflow problems. Because Java programmers have entrusted memory control to the Java virtual machine, memory leaks and spills can be a daunting task if you don’t know how the virtual machine is using memory.

2. Run time data area

During the execution of Java programs, the Java VIRTUAL machine divides the memory it manages into different data areas.

Some of these components are thread private and others are thread shared.

Thread private:

Program counter virtual machine stack local method stack

Thread shared:

Heap method area direct memory

2.1 Program counter

A program counter is a small memory space that can be viewed as a line number indicator of the bytecode being executed by the current thread. The bytecode interpreter works by changing the value of this counter to select the next bytecode instruction to be executed. Branches, loops, jumps, exception handling, thread recovery and other functions rely on this counter to complete.

In addition, in order to restore the thread to the correct execution position after switching, each thread needs to have an independent program counter, which does not affect each other and is stored independently. We call this kind of memory area “thread private” memory.

From the introduction above, we know that the program counter has two main functions:

1. Bytecode interpreter changes the program counter to read instructions in turn, so as to realize the flow control of code, such as sequential execution, selection, loop, exception handling. 2. In the case of multiple threads, the program counter is used to record where the current thread is executing, so that when the thread is switched back, it can know where it was last executed

Note: The program counter is the only memory area that does not have an OutOfMemoryError, and its life cycle is created with the creation of a thread and dies with the end of the thread.

2.2 Java Virtual Machine Stack

Like program counters, the Java virtual machine stack is thread-private and has the same lifecycle as a thread, describing an in-memory model of the execution of Java methods.

Java memory can be roughly divided into Heap memory and Stack memory, where the Stack is now referred to as the virtual machine Stack, or the local variable scale part of the virtual machine Stack. (Actually, the Java virtual machine stack is made up of stack frames, and each stack frame has: local variable table, operand stack, dynamic link, method exit information.)

The local variable table mainly stores various data types known by the compiler (Boolean, byte, CHAR, short, int, float, long, double), object references (reference type, which is different from 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.

There are two types of exceptions to the Java virtual machine stack: StackOverFlowError and OutOfMemoryError.

StackOverFlowError:

If the memory size of the Java virtual machine stack does not allow dynamic scaling, a StackOverFlowError is raised when the thread requests the stack depth beyond the current maximum depth of the Java virtual machine stack.

An OutOfMemoryError.

OutOfMemoryError is raised if the memory size of the Java virtual machine stack allows dynamic expansion, and the memory is exhausted when the thread requests the stack and cannot be dynamically expanded. The Java virtual machine stack is also thread-private, with each thread having its own Java virtual machine stack that is created as a thread is created and dies as a thread dies.

2.3 Local method stack

This function is very similar to that of the virtual machine stack, except that the virtual machine stack performs Java methods (that is, bytecode) services for the virtual machine, while the Native method stack serves Native methods used by the virtual machine. Integrate the HotSpot VIRTUAL machine with the Java virtual machine stack. When a local method is executed, a stack frame is also created on the local method stack to hold the local variable table, operand stack, dynamic link, and exit information for the local method.

StackOverFlowError and OutOfMemoryError are both StackOverFlowError and OutOfMemoryError.

2.4 the heap

The largest chunk of memory managed by a Java virtual machine, the Java heap is an area of memory 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 the point of view of garbage collection, the Java heap can be subdivided into: new generation and old generation: Eden space, From Survivor, To Survivor space, etc. The purpose of further partitioning is to better reclaim memory, or to allocate memory faster.

In JDK 1.8, the entire permanent generation was removed and replaced with an area called Metaspace (the permanent generation uses the JVM’s heap memory space, whereas the Metaspace uses physical memory and is directly limited by the native physical memory).

Recommended reading:

The Java8 memory model, permanent generation (PermGen) and yuan space (Metaspace) : www.cnblogs.com/paddix/p/53…

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.

The method area in the HotSpot VIRTUAL machine is also often referred to as a “persistent generation”, and the two are not essentially equivalent. It’s just that the HotSpot VIRTUAL machine design team implements the method area with persistent generations so that the HotSpot VIRTUAL machine garbage collector can manage this part of memory as well as the Java heap. This is not a good idea, however, because it is more likely to run into memory overflow problems.

Garbage collection is relatively rare in this area, but data is not “permanent” once it enters the method area.

2.6 Runtime constant pool

The runtime constant pool is part of the method area. In addition to the description of the Class version, fields, methods, interfaces, etc., 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.

JDK1.7 and later JVMS have moved the runtime constant pool out of the method area, creating an area in the Java Heap to house the runtime constant pool.

Recommended reading:

“Differentiating constant pools in Java” : blog.csdn.net/qq_26222859…

2.7 Direct Memory

Direct memory is not part of the virtual machine’s run-time data area, nor is it defined in the virtual machine specification, but it is frequently used. It may also cause an OutOfMemoryError to occur.

The NIO(New Input/Output) class added in JDK1.4 introduces an I/O mode based on Channel and Buffer, which can directly allocate out-of-heap memory using Native function library. 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.

Native direct memory allocation is not limited by the Java heap, but since it is memory, it is limited by the total native memory size and processor addressing space.

3 HotSpot VM object exploration

Here is the Java object creation process. I recommend writing it out by ear and knowing what you are doing at each step.

① Class loading check:

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.

② Allocating 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 types of allocation: “pointer collision” and “free list”, which allocation is determined by whether the Java heap is clean, which in turn is determined by whether the garbage collector used has collation capabilities.

Two ways to allocate memory :(supplementary content, need to master)

The choice between the two approaches depends on whether the Java heap memory is tidy. Whether the Java heap memory is clean depends on whether the GC collector’s algorithm is “mark-clean” or “mark-tidy” (also known as “mark-compress”). Notably, the copy-algorithm memory is clean as well

Memory allocation concurrency problem

There is a very important issue when creating objects, is thread safety, because in the actual development process, object creation is very frequent things, as a virtual machine, must ensure that thread safety, generally speaking, virtual machines use two ways to ensure thread safety:

CAS+ failed to retry:

CAS is an implementation of optimistic locking. Optimistic locking is when an operation is performed each time without locking, assuming no conflicts, and then retry until it succeeds if it fails because of conflicts. The CENTRAL Authentication Service (CAS) configuration fails to retry to ensure atomicity of update operations.

TLAB:

Each thread is allocated a block of memory in Eden area in advance. When THE JVM allocates memory to objects in the thread, it first allocates memory in TLAB. When the object is larger than the remaining memory in TLAB or the memory in TLAB is exhausted, the CAS mentioned above is used for memory allocation

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.

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.

Execute the init method:

After all the work is done, 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, methods have not been executed, and all fields are still zero. So, in general, a new instruction is followed by a method that initializes the object as the programmer wants it to be, and then a usable object is fully generated

3.2 Memory layout of objects

In the Hotspot VIRTUAL machine, the layout of objects in memory can be divided into three areas: object headers, instance data, and aligned padding.

Hotspot virtual machine object consists of two pieces of information, the first part of its own runtime data are used to store objects (hash code, GC generational age, lock status flag, etc.), the other part is a pointer type, namely the object pointer to its class metadata, virtual machine this object is determined by the pointer to the instance of the class.

The instance data part is the valid information that the object actually stores and the content of various types of fields defined in the program.

The alignment padding part is not necessarily there and has no special meaning. It just serves as a placeholder. Because the Hotspot VIRTUAL machine’s automatic memory management system requires that the object’s starting address be an integer multiple of 8 bytes, in other words, the object’s size must be an integer multiple of 8 bytes. The object header is exactly a multiple (1 or 2) of 8 bytes, so when the object instance data part is not aligned, it needs to be filled by alignment.

3.3 Object Access Location

Objects are created to use objects, and our Java program operates on specific objects on the heap using reference data on the stack. The object access mode depends on the IMPLEMENTATION of the VM. Currently, the mainstream access mode includes ① handle and ② direct pointer:

Handle:

If the handle is used, a chunk of memory will be allocated to the Java heap as the handle pool. Reference stores the handle address of the object, and the handle contains the specific address information of the instance data and type data of the object.

Direct pointer:

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.

Both object access methods have their own advantages. The biggest benefit of using handles for access is that reference stores a stable handle address and only changes the instance data pointer in the handle when the object is moved. Reference itself does not need to be modified. The biggest advantage of using direct pointer access is fast speed, it saves the time cost of a pointer location. 4. Key supplementary content

4.1 String classes and constant pools

4.1.1 Two Ways to Create a String object:

     String str1 = "abcd";
     String str2 = new String("abcd");
     System.out.println(str1==str2);//false
Copy the code

There is a difference between the two methods of creating objects in the constant pool and creating a new object directly in the heap memory space.

Remember: Whenever you use the new method, you need to create a new object.

4.1.2 String constant pools are special. It can be used in two main ways:

Strings declared directly in double quotes are stored directly in the constant pool. If a String object is not declared in double quotes, you can use the intern method provided by String. String. Intern () is a Native method that returns a reference to a String in the constant pool if the runtime constant pool already contains a String equal to the String. If not, a String with the same contents as this String is created in the constant pool and a reference to the String created in the constant pool is returned.

	      String s1 = new String("Computer");
	      String s2 = s1.intern();
	      String s3 = "Computer";
	      System.out.println(s2);/ / computer
	      System.out.println(s1 == s2);//false, because one is a String in the heap and the other is a String in the constant pool,
	      System.out.println(s3 == s2);//true, because both are strings in the constant pool
Copy the code

4.1.3 String String Concatenation

		  String str1 = "str";
		  String str2 = "ing";
		  
		  String str3 = "str" + "ing";// Objects in the constant pool
		  String str4 = str1 + str2; // Create a new object on the heap
		  String str5 = "string";// Objects in the constant pool
		  System.out.println(str3 == str4);//false
		  System.out.println(str3 == str5);//true
		  System.out.println(str4 == str5);//false
Copy the code

Avoid concatenating multiple strings, as this recreates the object. If you need to change strings, you can use StringBuilder or StringBuffer.

String s1 = new String(” ABC “); How many objects does this sentence create?

Two objects are created.

Validation:
		String s1 = new String("abc");// Heap memory address value
		String s2 = "abc";
		System.out.println(s1 == s2);// Print false because one is heap memory and the other is constant pool memory, so the two are different.
		System.out.println(s1.equals(s2));/ / output true
Copy the code
Results:
false
true
Copy the code
Explanation:

The string “ABC” is placed in the constant pool, and then a new copy of the string “ABC” is placed in the Java heap (the string constant “ABC” is determined in the constant pool at compile time, whereas the “ABC” on the Java heap is determined at runtime initialization). Str1 of the Java stack then points to “ABC” on the Java heap.

8 basic types of wrapper classes and constant pools

Most of the basic types of Java wrapper class implements the constant pool technology, namely, Byte, Short, Integer, Long, Character, and Boolean; These five wrapper classes create the corresponding type of cached data for the value [-128,127] by default, but new objects are still created beyond this range. The wrapper class Float,Double, for two floating-point types, does not implement constant pooling technology.

		Integer i1 = 33;
		Integer i2 = 33;
		System.out.println(i1 == i2);/ / output true
		Integer i11 = 333;
		Integer i22 = 333;
		System.out.println(i11 == i22);/ / output is false
		Double i3 = 1.2;
		Double i4 = 1.2;
		System.out.println(i3 == i4);/ / output is false
Copy the code

Integer cache source code:

/** * This method will always cache values in the range -128 to 127, including endpoints, and can cache other values outside this range. * /
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
Copy the code

Application Scenarios:

  1. The Integer i1 = 40; I1 = integer.valueof (40); i1= integer.valueof (40); To use objects in the constant pool.
  2. Integer i1 = new Integer(40); In this case, a new object is created.
  Integer i1 = 40;
  Integer i2 = new Integer(40);
  System.out.println(i1==i2);/ / output is false
Copy the code

Integer is a richer example:

  Integer i1 = 40;
  Integer i2 = 40;
  Integer i3 = 0;
  Integer i4 = new Integer(40);
  Integer i5 = new Integer(40);
  Integer i6 = new Integer(0);
  
  System.out.println("i1=i2 " + (i1 == i2));
  System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
  System.out.println("i1=i4 " + (i1 == i4));
  System.out.println("i4=i5 " + (i4 == i5));
  System.out.println("i4=i5+i6 " + (i4 == i5 + i6));   
  System.out.println("40=i5+i6 " + (40 == i5 + i6));   
Copy the code

Results:

i1=i2   true
i1=i2+i3   true
i1=i4   false
i4=i5   false
i4=i5+i6   true
40=i5+i6   true
Copy the code

Explanation:

Statement i4 == i5 + i6, since the + operator does not apply to Integer objects, first i5 and i6 are automatically unboxed, adding the values, i4 == 40. Then the Integer object cannot be directly compared to a numeric value, so i4 automatically unboxes itself to int 40, and finally the statement is converted to 40 == 40 for numeric comparison.