Why does Java distinguish between heap and stack in interview records

We all know the heap and the stack, but don't know why there are these. This article describes the principle

Table of contents

1. What is a heap and what is a stack

1.1 heap

1.2 stack

1.3 Summary

2. What will be stored in the heap

2.1 Java class instance object

2.2 Array objects

2.3 Member variables of object instances

2.4 Static variables

2.5 Constant pool:

2.5.1 Interesting constant pool

3. What will the stack store

3.1 Interesting stacks

Four. Summary


To put it simply, Java divides the heap and stack to better use memory and improve memory usage efficiency.

1. What is a heap and what is a stack

        Java's heap (Heap) and stack (Stack) are two different storage areas in memory, used to store data during program execution.

1.1 heap

        The heap is a tree-based data structure . Since the size of objects and arrays is not fixed, they cannot be stored in the stack memory, otherwise the stack memory will not be enough, so the heap is the place to store objects and their instance variables . The size of the heap is not fixed and is automatically managed by the virtual machine. When the heap space is insufficient, an OutOfMemoryError exception will be thrown. Heap memory is characterized by dynamic allocation and release, so the size of objects and arrays can be dynamically adjusted, and the use efficiency of heap memory is relatively high. At the same time, since the heap memory is discontinuous, the access speed is relatively slow.

        The heap is a tree data structure primarily because it needs to support efficient dynamic memory allocation and deallocation. In the heap, the memory space is organized in a tree structure, where each node represents a memory block, including the size and status (allocated or unallocated) of the memory block.

        The tree structure of the heap enables it to support efficient memory allocation and recovery operations. When a piece of memory needs to be allocated, the heap will traverse the tree starting from the root node, looking for a large enough unallocated memory block, and assigning it to the program. Similarly, when a block of memory needs to be released, the heap will start from the location of the memory block, recursively merge adjacent unallocated memory blocks to form a larger unallocated memory block, and finally restore the memory block to the unallocated status so that subsequent programs can continue to use it.

        Since the heap is a dynamic data structure, memory allocation and recovery are frequent operations. The tree structure has better scalability and flexibility, so the heap is designed as a tree structure to support efficient memory allocation and recovery.

1.2 stack

       The stack is a first-in, last-out data structure that stores references to basic types and objects (that is, pointers to where objects are stored in the heap). Each thread has its own stack space, and the size of the stack is fixed and small. , which is automatically managed by the virtual machine. When the stack space is insufficient, a StackOverflowError exception will be thrown. When a method is called, it creates a stack frame in stack memory, which stores information such as method parameters, local variables, and method return values. When the method execution completes, the stack frame is popped and removed from the stack memory. Since the data storage method of the stack memory is continuous, the access speed is relatively fast. At the same time, due to the dynamic creation and destruction of the stack frame, the management of the stack memory is relatively easy.

        The stack is a linear data structure that can only be inserted and deleted at the top of the stack. Because in the stack, the insertion and deletion of elements will only happen at the top of the stack, so this operation can be easily realized by using the array structure. Arrays can directly access elements at any position, so when inserting and deleting elements at the top of the stack, you only need to insert and delete at the end of the array, which can ensure that the time complexity of the operation is O(1). At the same time, using the array structure can also avoid the time and space overhead caused by frequent memory allocation and release, and improve the efficiency of the stack. Therefore, stacks are usually implemented using array structures.

1.3 Summary

        All threads share the same heap space, and the objects in it can be accessed by all threads, while the stack space is independent, and each thread has its own stack space.

  1. When a Java program is first compiled into bytecode by javac, it is loaded into memory through a class loader, and the execution engine will read these bytecode instructions and execute them.
  2. When the program starts, the JVM creates a main thread, and creates a private area such as a virtual machine stack, a local method stack, and a program counter for the thread.
  3. When a method is called, the execution engine creates a new stack frame containing information about the method and pushes it onto the top of the virtual machine stack. If an object needs to be created, memory is allocated on the heap and a reference to that object is placed on the stack. Static variables and constants are stored in the method area.
  4. When the execution is complete, the stack frame at the top of the virtual machine stack will be popped. Garbage collection runs automatically during program execution to reclaim unused memory.

2. What will be stored in the heap

2.1 Java class instance object

        When an object is created using the `new` keyword, the object is stored on the heap.

例如:`MyClass obj = new MyClass();` 中的 `obj` 对象就存储在堆中。

2.2 Array objects

        Arrays in Java are also objects, and array objects are also stored on the heap.

例如:`int[] arr = new int[5];` 中的 `arr` 数组对象就存储在堆中。

2.3 Member variables of object instances

        When a Java object contains member variables of other object types, these member variables are also stored in the heap.

例如: `MyClass` 类中,`value` 对象就存储在堆中。

public class MyClass {
    private String value;
    // ...
}

2.4 Static variables

        Static variables in Java are stored in the method area, but their initial values ​​are stored in the heap when the class is loaded.

例如: `MyClass` 类中的 `count` 静态变量的初始值就存储在堆中。

public class MyClass {
    private static int count = 0;
    // ...
}

2.5 Constant pool:

        The constant pool is quite special. Here are some interesting points

2.5.1 Interesting constant pool

        If the string is created using Stringthe class literal, the string object will be stored in the constant pool. For example, both of the following strings were literalcreated using , so they will be stored in the constant pool:

String str1 = "hello";
String str2 = "hello";

        Both str1 = "hello" and str2 = "hello" are string objects created as literal values, so they will be stored in the string constant pool. Since they have the same value, they actually refer to the same string constant object. So, str1 and str2 actually refer to the same object .       


         For string objects created by other means, such as using newthe operator or Stringthe constructor of the class, the string object will be stored in the heap. In this case, the reference to the string object str3is stored on the stack, while the actual contents of the string are stored on the heap. str3 and str1 are not an object . For example:

String str3 = new String("hello");

        In this code, the string "hello" will first check whether it exists in the constant pool. If it does not exist, a new string object will be created in the constant pool, and then a new string object will be created , and the constant pool A reference to the string object in is passed to this new string object. Because of the use of the new keyword, this new string object will allocate space in the heap memory. So in this code, the "hello" string creates an object in the constant pool and a new object in the heap memory.

3. What will the stack store

        In Java, each thread has its own stack. A stack is a Last-In-First-Out (LIFO) data structure, which is generally implemented using an array or a linked list. When a method is called, information such as parameters, local variables, and return address of the method are pushed onto the top of the stack, and when the method returns, the information is popped from the stack.

Okay, let's take the Java code as an example to briefly introduce the contents that may be stored in the stack.

public class StackExample {
    public static void main(String[] args) {
        int a = 1;
        String b = "hello";
        int[] arr = {1, 2, 3};
        System.out.println(a + b + arr[0]);
    }
}

1. A reference to the `args` parameter array, which points to a string array that contains the parameters passed to the main method when the program is running.
2. The `a` variable, which is an integer of a basic data type, is stored on the stack.
3. The `b` variable, which is a reference to a string object, is stored in the stack and points to a string object in the heap.
4. The `arr` variable, which is a reference to an array object of integer type, is stored in the stack and points to an integer array object in the heap.
5. The call stack frame of the `main` method contains information such as method parameters, local variables, and operand stack.

Because there will be a new stack frame every time the method is called, the stack also has some interview points

3.1 Interesting stacks

public static void main(String[] args) {
    MyClass obj = new MyClass();
    obj.setValue(5);
    System.out.println(obj.getValue()); // 输出5

    foo(obj);
    System.out.println(obj.getValue()); // 输出10
}

public static void foo(MyClass obj) {
    //obj = new MyClass();
    obj.setValue(10);
}

        In this code, we define a MyClassclass that contains an integer property valueand access methods for that property. In mainthe method, we create an MyClassobject objand valueset its property to 5. We then called a foomethod called , objwhich we will pass as a parameter. Inside foothe method, we set objthe pointed-to object's valueproperty to 10. In mainthe method, we output the attribute again obj, valueand the output result is 10 at this time.


public static void main(String[] args) {
    MyClass obj = new MyClass();
    obj.setValue(5);
    System.out.println(obj.getValue()); // 输出5

    foo(obj);
    System.out.println(obj.getValue()); // 输出5
}

public static void foo(MyClass obj) {
    obj = new MyClass();
    obj.setValue(10);
}

        In this code, we define a  MyClass class that contains an integer property  value and access methods for that property. In  main the method, we create an  MyClass object  obj and  value set its property to 5. We then called a  foo method called ,  obj which we will pass as a parameter. Inside  foo the method, we assign obj to a new reference, and then assign a value to the new reference obj. At this time, there are actually 2 objects. After foo is called, its stack frame is destroyed, so the original object remains unchanged, and 5 is output.

Four. Summary

        During the interview, you must remember the concept and basic structure of stack and heap

the stack heap
Store thread-private data store shared data
Array or linked list implementation tree structure
relatively fast access Relatively slow access

        Also note that in Java, whether it is a basic data type or a custom object, parameter passing is value passing. This means that when we pass a custom object as a parameter to a method, what is actually passed is a copy of the reference. When the method internally modifies the properties of the object pointed to by the reference, it will affect the object pointed to by the original reference. But when the method internally points the reference to a new object, it will not affect the object pointed to by the original reference. 

Guess you like

Origin blog.csdn.net/qq_37761711/article/details/130569458