Home  >  Article  >  Java  >  Detailed introduction to Java heap memory and stack memory

Detailed introduction to Java heap memory and stack memory

高洛峰
高洛峰Original
2017-01-24 14:44:531728browse

Heap and stack in Java Java divides memory into two types: one is stack memory and the other is heap memory.

Some basic type variables 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 scope of the variable is exceeded, Java will automatically release the memory space allocated for the variable, and the memory space can be immediately used. Use it for other purposes.

Heap memory is used to store objects and arrays created by new. The memory allocated in the heap is managed by the Java virtual machine automatic garbage collector. After an array or object is generated in the heap, you can also define a special variable in the stack. The value of this variable is equal to the first address of the array or object in the heap memory. This special variable in the stack becomes After obtaining the reference variable of the array or object, you can use the reference variable in the stack memory to access the array or object in the heap in the program. The reference variable is equivalent to an alias or code name for the array or object.

Reference variables are ordinary variables. Memory is allocated on the stack when defined. Reference variables are released outside the scope when the program runs. The array & object itself is allocated in the heap. Even if the program runs outside the code block where the statement using new to generate the array and object is located, the heap memory occupied by the array and object itself will not be released. The array and object will not be pointed to by reference variables. When it is used, it becomes garbage and can no longer be used, but it still occupies memory and is released by the garbage collector at an unspecified time later. This is also the main reason why Java takes up more memory. In fact, the variables in the stack point to variables in the heap memory. This is the pointer in Java!

Heap and stack in Java

Java divides memory into two types: one is stack memory and the other is heap memory.

1. Stack and heap are places used by Java to store data in Ram. Unlike C++, Java automatically manages the stack and heap, and programmers cannot directly set the stack or heap.

 2. The advantage of the stack is that the access speed is faster than the heap, second only to the registers directly located in the CPU. 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. Additionally, stack data can be shared. 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. Java's garbage collector will automatically collect the data that is no longer used. But the disadvantage is that due to the need to dynamically allocate memory at runtime, the access speed is slow.​

  3. There are two types of data types in Java.

One is the basic type (primitive types), there are 8 types in total, namely int, short, long, byte, float, double, boolean, char (note that
does not have the basic type of string). This type of definition is defined in the form such as int a = 3; long b = 255L; and is called an automatic variable. It is worth noting that automatic variables store literal values, not instances of classes, that is, they are not references to classes. There is no class here. For example, int a = 3; where a is a reference pointing to type int,

points to the literal value 3. The data of these literal values ​​can be known because their size and lifetime are known (these literal values ​​are fixedly defined in a certain program block, and after the program block exits, the field values ​​disappear),

Out of pursuit The reason for speed exists in the stack.

In addition, the stack has a very important special feature, that is, the data stored in the stack can be shared. Suppose we define at the same time:

int a = 3;
int b = 3;

The compiler processes int a = 3 first; first it will be on the stack Create a reference to the variable a in , and then search to see if there is an address with a literal value of 3. If it is not found, open an address to store 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 on the stack, b will be pointed directly to the address of 3. In this way, there is a situation where a and b both point to 3 at the same time.

It is important to note that the reference of this literal value is different from the reference of the class object. Assume that the references of two class objects point to the same object at the same time. If one object reference variable modifies the internal state of the object, then the other object reference variable will immediately reflect the change. In contrast, modifying the value of a literal reference does not cause the value of another reference to the literal to also change. As in the above example, after we define the values ​​of a and b, we then set a=4; then, b will not be equal to 4, but still equal to 3. Inside the compiler, when it encounters a=4;, it will re-search whether there is a literal value of 4 on the stack. If not, it will re-open an address to store the value of 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.

The other is wrapper class data, such as Integer, String, Double and other classes that wrap the corresponding basic data types. All these types of data exist in the heap. Java uses the new() statement to explicitly tell the compiler that it will be dynamically created as needed at runtime, so it is more flexible, but the disadvantage is that it takes more time.

In JAVA, there are six different places where data can be stored:

1. Register. This is the fastest memory area because it is located in a different place than the other memory areas - inside the processor. However, the number of registers is extremely limited, so registers are allocated by the compiler according to needs. You have no direct control, nor can you feel any hint of the register's existence in the program.

2. Stack. Located in general-purpose RAM, but supported by the processor via its "stack pointer". If the stack pointer moves downward, new memory is allocated; if it moves upward, that memory is released. This is a fast and efficient method of allocating storage, second only to registers. When creating a program, the JAVA compiler must know the exact size and lifetime of all data stored on the stack, because it must generate the appropriate code to move the stack pointer up and down. This constraint limits the flexibility of the program, so although some Java data is stored on the stack - specifically object references, Java objects are not stored there.

3. Heap. A universal memory pool (also present in RAM) used to store all JAVA objects. The advantage of the heap being different from the stack is that the compiler does not need to know how much storage area to allocate from the heap, nor does it need to know how long the stored data will survive in the heap. Therefore, there is great flexibility in allocating storage on the heap. When you need to create an object, you only need to write a simple line of new code. When this line of code is executed, storage will be automatically allocated in the heap. Of course, this flexibility must be paid for with corresponding code. Storage allocation using the heap takes more time than storage using the stack.

4. Static storage. "Static" here means "in a fixed position". Static storage stores data that exists while the program is running. You can use the keyword static to identify specific elements of an object as static, but the JAVA object itself is never stored in static storage space.

5. Constant storage. Constant values ​​are usually stored directly within the program code, which is safe because they can never be changed. Sometimes, in embedded systems, the constant itself will be separated from other parts, so in this case, you can choose to put it in ROM

6. Non-RAM storage. If the data survives completely outside the program, then it can exist without any control of the program and can exist even when the program is not running.
In terms of speed, there is the following relationship:

Register< Stack< Heap< Others

『The above paragraph is excerpted from "Thinking in Java" 』

Question one:

String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true

Question two:

String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false

Question 3:

String s1 = "ja";
String s2 = "va";
String s3 = "java";
String s4 = s1 + s2;
System.out.println(s3 == s4);//false
System.out.println(s3.equals(s4));//true

Some basic type variables 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 scope of the variable is exceeded, Java will automatically release the memory space allocated for the variable. This memory space can be immediately put to another use.

Heap memory is used to store objects and arrays created by new.

The memory allocated in the heap is managed by the automatic garbage collector of the Java virtual machine.

After generating an array or object in the heap, you can also define a special variable 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 a reference variable of the array or object.

A reference variable is equivalent to giving a name to an array or object. In the future, you can use the reference variable in the stack to access the array or object in the heap in the program.
Specifically: Stack and heap are places used by Java to store data in Ram. Unlike C++, Java automatically manages the stack and heap, and programmers cannot directly set the stack or heap.

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. Heap It is responsible for garbage collection. 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 unused The data is reused. But the disadvantage is that the access speed is slow because the memory needs to be dynamically allocated at runtime.

      栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。  

      栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:  

int a = 3;  
int b = 3;  

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。  

String是一个特殊的包装类数据。可以用:  

String str = new String("abc");
String str = "abc";

   

两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。  
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。 

          比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。  

String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true

   

可以看出str1和str2是指向同一个对象的。 

String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false

   

用new的方式是生成不同的对象。每一次生成一个。  

   因此用第二种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。  

   另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。(不一定,因为如果事先没有,那么就会创建,这就是创建对象了,如果原来就有,那就指向那个原来的对象就可以了)!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。 

更多Java 堆内存与栈内存详细介绍相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn