Home  >  Article  >  Java  >  In-depth understanding of Java memory allocation (pictures and text)

In-depth understanding of Java memory allocation (pictures and text)

黄舟
黄舟Original
2017-03-27 10:50:501542browse

This article mainly introduces relevant information for an in-depth understanding of Java memory allocation. Friends who need it can refer to

In-depth understanding of Java memory allocation

This article will be written in a simple way This article introduces the principles of Java memory allocation in depth to help novices learn Java more easily. There are many such articles online, but most of them are fragmented. This article will give readers a systematic introduction from the perspective of cognitive processes.

The first thing you need to know before getting into the topic is that Java programs run on JVM (Java Virtual Machine, Java Virtual Machine). JVM can be understood as a bridge between Java programs and operating systems. JVM implements Java Platform independence shows the importance of JVM. Therefore, when learning the principles of Java memory allocation, you must remember that everything is done in the JVM. The JVM is the foundation and premise of the memory allocation principle.

                                                                                                                                                                The running process of a complete Java program can involve the following memory areas: The access speed is very fast and the program is uncontrollable.

L

stack: Save the local variable

value, including: 1. Use to save the value of the basic data type; ##, that is, the reference (pointer) of the

object in the heap area. Can also be used to save frames when loading methods.                                                                                                                                                                  . Note that the created objects only contain their respective member variables and do not include member methods. Because objects of the same class have their own member variables and are stored in their own heaps, but they share the methods of the class, member methods are not copied every time an object is created.                     1 Constant pool: JVM maintains a constant pool for each loaded type. The constant pool is an ordered collection of constants used by this type. Including direct constants (basic types, String) and symbol references to other types, methods, and fields (1)

. Data in the pool is accessed via index just like arrays. Because the constant pool contains all symbolic references of a type to other types, methods, and fields, the constant pool plays a core role in Java's dynamic linking.

The constant pool exists in the heap.                                                                                                             

                                                                                             . The following is the memory representation diagram:

# It roughly describes Java memory allocation, and then explains in detail how Java programs run in memory through examples (Note: The following pictures are quoted from the J2SE courseware of Teacher Ma Bingbing of Shangxuetang. The right side of the picture is the program code, and the left side is the memory. Assignment diagram, I will add notes one by one). Preliminary knowledge:

##       1.

A Java file, as long as there is a main entry method, we consider it A Java program can be compiled and run independently.
2.

Whether it is a common type variable or a reference type variable (commonly known as an instance), it can be used as a local variable, and they can all appear on the stack. It's just that ordinary type variables store their corresponding values ​​directly on the stack, while reference type variables store a pointer to the heap area. Through this pointer, you can find the object corresponding to this instance in the heap area. Therefore, ordinary type variables only occupy a piece of memory in the stack area, while reference type variables occupy a piece of memory in the stack area and heap area.

In-depth understanding of Java memory allocation (pictures and text)Example:

##       

1.

The JVM automatically finds the main method, executes the first line of code, creates an instance of the Test class, allocates a piece of memory in the stack, and stores a pointer 110925 pointing to the heap area object.

          2.Create an int type variable date. Since it is a basic type, the value 9 corresponding to date is directly stored in the stack.

          3.Create two instances of the BirthDate class, d1 and d2, and store corresponding pointers pointing to their respective objects in the stack. They call the constructor with parameters when instantiating, so there are custom initial values ​​in the object.

In-depth understanding of Java memory allocation (pictures and text)

##         Call the change1 method of the test object with date as the parameter. When the JVM reads this code, it detects that i is a local variable, so it puts i on the stack and assigns the value of date to i.

In-depth understanding of Java memory allocation (pictures and text)

                      Assign 1234 to i. Very simple step.

In-depth understanding of Java memory allocation (pictures and text)

##         After the change1 method is executed, the stack space occupied by the local variable i is immediately released.

In-depth understanding of Java memory allocation (pictures and text)

##        

Call the change2 method of the test object, taking instance d1 as the parameter. The JVM detects that the b parameter in the change2 method is a local variable and immediately adds it to the stack. Since it is a reference type variable, b stores the pointer in d1. At this time, b and d1 point to objects in the same heap. What is passed between b and d1 is a pointer.

In-depth understanding of Java memory allocation (pictures and text)

A BIRTHDATE object is instantiated and assigned to B. The internal execution process is: create a new object in the heap area, and save the pointer of the object in the space corresponding to b in the stack. At this time, instance b no longer points to the object pointed to by instance d1, but the object pointed to by instance d1 There is no change, so it cannot have any impact on d1.

In-depth understanding of Java memory allocation (pictures and text)

         After the change2 method is executed, the stack space occupied by the local reference variable b is immediately released. Note that it is only released. If the stack space is lost, the heap space must wait for automatic recycling.

In-depth understanding of Java memory allocation (pictures and text)

##        Call the change3 method of the test instance, taking instance d2 as the parameter. In the same way, the JVM will allocate space for the local reference variable b on the stack and store the pointer in d2 in b. At this time, d2 and b point to the same object. Then calling the setDay method of instance b actually calls the setDay method of the object pointed to by d2.

In-depth understanding of Java memory allocation (pictures and text)

##          Calling the setDay method of instance b will affect d2, because both point to the same an object.

In-depth understanding of Java memory allocation (pictures and text)
After the change3 method is executed, the local reference variable b is released immediately.


The above is the general situation of memory allocation when a Java program is running. In fact, it’s nothing. It’s very simple once you master the idea. There are nothing more than two types of variables: basic types and reference types. Both are placed on the stack as local variables. The basic type saves the value directly on the stack. The reference type only saves a pointer to the heap area, and the real object is in the heap. When used as a parameter, the basic type is passed directly by value, and the reference type is passed by the pointer.

Summary:

       

1.

Clear what is an instance and what is an object. Class a= new Class();At this time a is called an instance, but it cannot be said that a is an object. The instance is on the stack and the object is on the heap. Operating the instance actually operates the object indirectly through the instance pointer. Multiple instances can point to the same object.

                2.The data in the stack and the data in the heap are not destroyed synchronously. Once the method ends, the local variables in the stack are destroyed immediately, but the objects in the heap are not necessarily destroyed. Because there may be other variables pointing to this object, it will not be destroyed until there are no variables in the stack pointing to the object in the heap, and it will not be destroyed immediately. It will not be destroyed until the garbage collection scan.

         3.The above stack, heap, code segment, data segment, etc. are all relative to the application program. Each application corresponds to a unique JVM instance. Each JVM instance has its own memory area and does not affect each other. And these memory areas are shared by all threads. The stacks and heaps mentioned here are overall concepts, and these stacks can also be subdivided.

        4.The member variables of a class are different in different objects and have their own storage space (member variables are in objects in the heap). However, the methods of a class are shared by all objects of the class. There is only one set. The methods are pushed onto the stack when the object uses the method. If the method is not used, it does not occupy memory.

The above analysis only involves the stack and heap, and there is also a very important memory area: the constant pool, where some inexplicable problems often occur. The purpose of the constant pool has been explained above, and there is no need to understand it deeply. Just remember that it maintains the constants of a loaded class. Next, we will illustrate the characteristics of the constant pool with some examples.

Preliminary knowledge:

Basic types and wrapper classes of basic types. The basic types are: byte, short, char, int, long, boolean. The basic types of packaging classes are: Byte, Short, Character, Integer, Long, and Boolean. Note that it is case sensitive. The difference between the two is: the basic type is reflected in the program as an ordinary variable, and the wrapper class of the basic type is a class, which is reflected in the program as a reference variable. Therefore, they are stored in different locations in memory: primitive types are stored on the stack, while primitive wrapper classes are stored on the heap. The wrapper classes mentioned above all implement constant pool technology, but the other two floating-point number type wrapper classes do not. In addition, the String type also implements constant pool technology.

Example:

public class test { 
  public static void main(String[] args) {   
    objPoolTest(); 
  } 
 
  public static void objPoolTest() { 
    int i = 40; 
    int i0 = 40; 
    Integer i1 = 40; 
    Integer i2 = 40; 
    Integer i3 = 0; 
    Integer i4 = new Integer(40); 
    Integer i5 = new Integer(40); 
    Integer i6 = new Integer(0); 
    Double d1=1.0; 
    Double d2=1.0; 
     
    System.out.println("i=i0\t" + (i == i0)); 
    System.out.println("i1=i2\t" + (i1 == i2)); 
    System.out.println("i1=i2+i3\t" + (i1 == i2 + i3)); 
    System.out.println("i4=i5\t" + (i4 == i5)); 
    System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));   
    System.out.println("d1=d2\t" + (d1==d2));  
     
    System.out.println();     
  } 
}

Result:

i=i0  true 
i1=i2  true 
i1=i2+i3    true 
i4=i5  false 
i4=i5+i6    true 
d1=d2  false

ResultAnalysis:

1.i and i0 are both ordinary type (int) variables, so the data is stored directly in the stack, and the stack has a very important feature: In the stack The data can be shared. When we define int i = 40;, and then define int i0 = 40;, we will automatically check whether there is 40 in the stack. If so, i0 will directly point to i's 40, and no new 40 will be added.

2.i1 and i2 are both reference types and store pointers on the stack because Integer is a wrapper class. Since the Integer packaging class implements constant pool technology, the 40 of i1 and i2 are both obtained from the constant pool and point to the same address, so i1=12.

  3.Obviously this is an addition operation, Java’s mathematical operations are all performed on the stack, Java will automatically add i1 and i2 The unboxing operation is performed and converted into an integer type , so i1 is numerically equal to i2+i3.

      4.i4 and i5 are both reference types and store pointers on the stack because Integer is a wrapper class. However, since they are each new, they no longer look for data from the constant pool, but new an object from the heap, and then each saves the pointer to the object, so i4 and i5 are not equal because they store different pointers. The pointed objects are different.

5.This is also an addition operation, the same as 3.

        6.d1 and d2 are both reference types and store pointers on the stack because Double is a wrapper class. However, the Double packaging class does not implement constant pool technology, so Doubled1=1.0; is equivalent to Double d1=new Double(1.0);, which is a new object from the heap, and the same is true for d2. Therefore, the pointers stored in d1 and d2 are different and point to different objects, so they are not equal.

summary:

1.The basic types of packaging classes mentioned above all implement constant pool technology, but the constants they maintain are only constants in the range [-128 to 127]. If the constant value Beyond this range, objects will be created from the heap and will no longer be taken from the constant pool. For example, if the above example is changed to Integer i1 = 400; Integer i2 = 400;, it is obvious that it exceeds 127, and the constant cannot be obtained from the constant pool, so a new Integer object must be created from the heap. At this time, i1 and i2 are not equal. .

2.String type also implements constant pool technology, but it is slightly different. The String type first detects whether there is a corresponding string in the constant pool. If there is, it will be taken out; if not, the current one will be added.

Footnote:

(1) Symbol reference, as the name suggests, is a symbol. Symbol reference is This symbol will be parsed only when used. If you are familiar with Linux or Unix system, you can think of this symbol reference as a soft link to a file. When you use this soft link, it will actually be parsed and expanded to find the actual file

For symbol references, there are more discussions at the class loading level, and the source code level is just a formal discussion.

When a class is loaded, the symbolic references of other classes used by the class will be saved in the constant pool. When the actual code is executed, when it encounters another class for the first time, the JVM will save it in the constant pool. The symbolic reference of the class is expanded and converted into a direct reference, so that the next time the same type is encountered, the JVM will no longer parse it, but directly use this direct reference that has been parsed.

In addition to the above symbolic reference statement in the class loading process, at the source code level, it is based on the reference parsing process to distinguish whether certain data in the code is a symbolic reference or a direct reference, such as System. out.println("test" +"abc");//The effect happening here is equivalent to a direct reference, and assuming a Strings = "abc"; System.out. println("test" + s);//The effect here is equivalent to a symbolic reference, that is, s is expanded and parsed, which is equivalent to s being a symbolic link of "abc", that is to say, in the compiled At this time, the class file does not directly expand s, but treats this s as a symbol, which will be expanded when the actual code is executed.

The above is the detailed content of In-depth understanding of Java memory allocation (pictures and text). For more information, please follow other related articles on the PHP Chinese website!

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