1. Basic concepts
Each Java program runs will generate a java process. Each java process may contain one or more threads. Each Java process corresponds to a unique JVM instance, each JVM instance corresponds to a heap, and each thread has its own private stack. All instances of classes (that is, objects) or arrays (referring to the array itself, not references) created by a process are placed in the heap and shared by all threads of the process. The allocated heap memory in Java is automatically initialized, that is, when allocating memory to an object, the variables in the object will be initialized. Although the storage space of all objects in Java is allocated in the heap, the reference to this object is allocated in the stack, that is, when an object is created, memory is allocated in the heap and the stack. The memory allocated in the heap actually stores the created object itself, while the memory allocated in the stack only stores references to the heap object. When the local variable new comes out, space is allocated in the stack space and heap space. When the local variable life cycle ends, the stack space is immediately recycled, and the heap space area is waiting for GC to recycle.
Specific concept: The memory of a JVM can be divided into three areas: heap, stack and method area (method, also called static area):
Stack area:
1. All stored are objects, and each object contains information corresponding to it (the purpose of class is to obtain operation instructions);
2.jvm has only one heap area (heap) and is shared by all threads. The heap does not store basic types and object references, but only the object itself and the array itself;
Stack area:
1. Each thread contains a stack area, which only saves references to the basic data type itself and custom objects;
2. The data (primitive type and object reference) in each stack are private and cannot be accessed by other stacks;
3. The stack is divided into 3 parts: basic type variable area, execution environment context, and operation instruction area (storing operation instructions);
Method area (static area):
1. Shared by all threads. The method area contains all classes (class refers to the original code of the class. To create a class object, the code of the class must be loaded into the method area and initialized) and static variables.
2. The method area contains elements that are always unique in the entire program, such as class and static variables.
2. Example demonstration
AppMain.java
public class AppMain //When running, jvm puts all the appmain code into the method area { public static void main(String[] args) //The main method itself is placed in the method area. { Sample test1 = new Sample( " Test 1 " ); //test1 is a reference, so put in the stack area, Sample is a custom object, which should be placed in the heap. Sample test2 = new Sample( " Test 2 " ); test1.printName(); test2.printName(); } } public class Sample //When running, jvm puts all the information of appmain into the method area { /** Example name*/ private String name; //After new Sample instance, name reference is placed in the stack area, name corresponding String object is placed in the heap/** Constructor*/ public Sample(String name) { this .name = name; } /** Output */ public void printName() //When there is no object, the print method is placed in the method area along with the sample class. { System.out.println(name); } }When running the program, first start a Java virtual machine process. This process first finds the AppMain.class file from the classpath, reads the binary data in the file, and then stores the class information of the Appmain class in the method area of the runtime data area. This is the loading process of the AppMain class.
Next, the Java virtual machine locates the bytecode of the Main() method of the AppMain class in the method area and starts executing its instructions. The first statement of this main() method is:
The code copy is as follows:
Sample test1=new Sample("test1");
The execution process of this statement:
1. The Java virtual machine found the type information of the Sample class in the method area, but it was not found, because the Sample class has not been loaded into the method area (it can be seen here that the internal classes in Java exist separately, and at the beginning, it will not be loaded with the containing class, and will not be loaded until it is used). The Java virtual machine immediately loads the Sample class and stores the Sample class type information in the method area.
2. The Java virtual machine first allocates memory for a new Sample instance in the heap area, and stores a memory address in the method area where the Sample class type information is stored in the memory of the Sample instance.
3. In the JVM process, each thread will have a method call stack, which is used to track a series of method call processes during the thread's running. Each element in the stack is called a stack frame. Whenever a thread calls a method, a new frame will be pushed into the method stack. The frames here are used to store the parameters of the method, local variables, and temporary data during the operation.
4. Test1 before "=" is a variable (a reference to a Sample object) defined in the main() method, so it will be added to the JAVA method call stack of the main thread that executes the main() method. And "=" will point this test1 variable to the Sample instance in the heap area.
5. The JVM continues to create another Sample instance in the heap area, and adds a Test2 variable to the method call stack of the main method, which points to the new Sample instance just created in the heap area.
6. The JVM executes their printName() method in turn. When the JAVA virtual machine executes the test1.printName() method, the JAVA virtual machine locates the Sample instance in the heap area based on the reference held by the local variable test1, and then locates the Sample class type information in the method based on the reference held by the Sample instance, thereby obtaining the bytecode of the printName() method, and then executes the instructions contained in the printName() method to start execution.
III. Distinguish
The difference between heap and stack in Java language:
1. Stack and heap are both places used by Java to store data in Ram. Unlike C++, Java automatically manages stacks and heaps, and programmers cannot set up stacks or heaps directly.
2. The advantage of the stack is that the access speed is faster than the heap, second only to the registers located directly in the CPU. But the disadvantage is that the data size and lifetime in the stack must be deterministic and lack flexibility. In addition, stack data can be shared (see the introduction below for details). The advantage of the heap is that it can dynamically allocate memory size, and the lifetime does not have to be told to the compiler in advance. Java's garbage collector will automatically collect the data that is no longer used. But the disadvantage is that the memory must be dynamically allocated at runtime, the access speed is slower.
2 data types in Java:
One is the primitive types, with 8 types int, short, long, byte, float, double, boolean, char (note that there is no basic type of string). This type of definition is defined by a form such as int a = 3; long b = 255L; and is called an automatic variable. Automatic variables have literal values, not instances of classes, that is, they are not references to classes, and there is no class here. For example, int a = 3; here a is a reference pointing to the int type, pointing to the literal value of 3. Due to the size and lifetime of these literal data, these literal values are fixedly defined in a program block, and the field value disappears after the program block exits), and exists in the stack for the sake of pursuing speed.
The stack has a very important feature: the data that exists in the stack can be shared. Suppose we define at the same time: int a = 3; int b = 3; The compiler first processes int a = 3; first it will create a reference with a variable a in the stack, and then find out if there is an address with a literal value of 3. If it is not found, it will open an address with the literal value of 3, and then point a to the address of 3. Then process int b = 3; after creating the reference variable of b, since there is already a literal value of 3 in the stack, b is directly pointed to the address of 3. In this way, a and b both point to 3 at the same time.
This reference to literal values is different from that of class objects. Assuming that the references of two class objects point to an object at the same time, if one object reference variable changes the internal state of the object, the other object reference variable immediately reflects this change. Instead, modifying its value through a literal reference will not cause another value to be changed accordingly. As in the above example, after we define the values of a and b, let a=4; then, b will not be equal to 4, or equal to 3. Inside the compiler, when a=4 is encountered, it will re-search whether there is a literal value of 4 in the stack. If not, re-open the address to store the value of 4; if it already exists, directly point a to this address. Therefore, the change in value a will not affect the value b.
Another type is packaging class data, such as Integer, String, Double, etc. that wraps the corresponding basic data types. All of these class data exists in the heap. Java uses the new() statement to display the compiler and only creates dynamically as needed at runtime, so it is more flexible, but the disadvantage is that it takes up more time.
4. Summary
The java memory allocation structure is still very clear. If you want to understand it thoroughly, you can check JVM-related books. In Java, the most troublesome thing about memory allocation is the String object. Due to its special nature, many programmers are prone to confusion. I will explain it in detail in the next article.