This article mainly explains its working principle in detail by analyzing the stack, heap and constant pool of Java memory allocation.
1. Java virtual machine memory prototype
Register: We have no control over the program. Stack: stores basic types of data and object references, but the object itself is not stored on the stack, but is stored in the heap. Heap: stores the data generated with new. Static domain: is stored in the object. Static member constant pool defined with static: stores constants. Non-RAM storage: permanent storage space such as hard disk.
2. Constant pool
The constant pool refers to the constant pool that is determined at compile time and saved in the compiled memory. Some data in the class file. In addition to the constant values (final) that contain various basic types (such as int, long, etc.) and object types (such as String and arrays) defined in the code, it also contains some symbolic references in text form, such as:
1. Fully qualified names of classes and interfaces;
2. Field name and descriptor;
3. Methods, names and descriptors.
The virtual machine must maintain a constant pool for each loaded type. The constant pool is an ordered set of constants used by this type, including direct constants (string, integer and floating point constants) and symbolic references to other types, fields and methods. For String constants, their values are in the constant pool. The constant pool in the JVM exists in the form of a table in memory. For the String type, there is a fixed-length CONSTANT_String_info table used to store literal string values. Note: This table only stores literal string values, not symbols. Quote. Having said this, you should have a clear understanding of the storage location of string values in the constant pool. When the program is executed, the constant pool will be stored in the Method Area instead of the heap.
3. Stack in Java memory allocation
The basic unit of the stack is the frame (or stack frame): whenever a Java thread runs, the Java virtual machine allocates a Java stack to the thread. When the thread executes a certain Java method, it pushes a frame into the Java stack. This frame is used to store parameters, local variables, operands, intermediate operation results, etc. When this method completes execution, the frame will be popped from the stack. All data on the Java stack is private, and no other thread can access the thread's stack data. Some basic types of variable data and object reference variables defined in the function are allocated in the stack memory of the function. When a variable is defined in a block of code, Java allocates memory space for the variable on the stack. When the variable exits the scope, Java will automatically release the memory space allocated for the variable, and the memory space can be used immediately. be used for other purposes.
4. Heap in Java memory allocation
The heap in the Java virtual machine is used to store objects and arrays created by new. The memory allocated in the heap is managed by the automatic garbage collection mechanism of the Java virtual machine. To put it simply, compared with the stack, the heap is mainly used to store Java objects, and the stack is mainly used to store object references... After an array or object is generated in the heap, a special variable can also be defined in the stack, so that The value of this variable in the stack is equal to the first address of the array or object in the heap memory. This variable in the stack becomes the reference variable of the array or object. A reference variable is equivalent to giving a name to an array or object. You can then use the reference variable in the stack to access the array or object in the heap in the program. A reference variable is equivalent to giving a name to an array or object.
Reference variables are ordinary variables that are allocated on the stack when defined. The reference variables are released after the program runs outside its scope. The arrays and objects themselves are allocated in the heap. Even if the program runs outside the code block where the statement using new to generate the array or object is located, the memory occupied by the array and object itself will not be released. Arrays and objects have no reference variables pointing to them. , it becomes garbage and cannot be used anymore, but it still occupies the memory space and will be collected (released) by the garbage collector at an indeterminate time later. This is also the reason why Java takes up more memory. In fact, variables in the stack point to variables in the heap memory. This is a pointer in Java!
Java's heap is a runtime data area from which class objects allocate space. These objects are created through instructions such as new, newaray, anewarray, and multianewarray, and they do not require program code to be explicitly released. The heap is collected by garbage collection Responsible, the advantage of the heap is that it can dynamically allocate memory size, and the lifetime does not need to be told to the compiler in advance, because it dynamically allocates memory at runtime, and Java's garbage collector will automatically collect these no longer used data. But the disadvantage is that due to the need to dynamically allocate memory at runtime, the access speed is slow.
The advantage of the stack is that the access speed is faster than the heap, second only to the register, and the stack data can be shared. But the disadvantage is that the size and lifetime of the data stored in the stack must be determined and there is a lack of flexibility. The stack mainly stores some basic types of variable data (int, short, long, byte, float, double, boolean, char) and object handles (references).
A very important special feature of the stack is that the data stored in the stack can be shared. Suppose we also define:
int a=3; int b=3; The compiler first processes int a = 3; first it creates a reference to the variable a on the stack, and then checks whether there is a value of 3 on the stack. If not found, it will set 3 Store it in, and then point a to 3. Then process int b = 3; after creating the reference variable of b, because there is already a value of 3 on the stack, b will be pointed directly to 3. In this way, a and b appear. At the same time, both point to the case of 3.
At this time, if a=4 is set again; then the compiler will re-search whether there is a 4 value in the stack. If not, it will store 4 in and make a point to 4; if it already exists, it will directly point a to this address. . Therefore, changes in the value of a will not affect the value of b.
It should be noted that this kind of data sharing is different from the sharing of two objects' references pointing to one object at the same time, because in this case the modification of a will not affect b, it is completed by the compiler, which is beneficial to Save space. If an object reference variable modifies the internal state of the object, it will affect another object reference variable.