Detailed explanation of stack in java -

Specifically: http://www.verydemo.com/demo_c89_i11161.html

1. Both stack and heap are places where Java uses to store data in Ram. Unlike C++, Java automatically manages the stack and heap, and the programmer cannot set the stack or heap 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 size and lifetime of the data stored in the stack must be deterministic, which lacks flexibility. In addition, stack data can be shared, see point 3 for details. The advantage of the heap is that the memory size can be dynamically allocated, and the lifetime does not have to be told to the compiler in advance, and the Java garbage collector will automatically collect these no longer used data. But the disadvantage is that the access speed is slower due to the dynamic allocation of memory at runtime.

  3. There are two types of data in Java.

  One is primitive types, there are 8 types, namely int, short, long, byte, float, double, boolean, char (note that there is no basic type of string). This type of definition is defined by something like 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, not references to classes. There is no class here. Such as int a = 3; where a is a reference to int type, pointing to the literal value of 3. The data of these literal values, because the size is known, the lifetime is known (these literal values ​​are fixed in a certain program block, after the program block exits, the field value disappears), for the pursuit of speed, it exists in the stack. .

  In addition, the stack has a very important particularity, that is, the data stored in the stack can be shared. Suppose we define both:

int a = 3;
int b = 3;

  The compiler first processes int a = 3; first, it will create a reference to the variable a in the stack, and then look for an address with a literal value of 3. If not found, it will open an address to store the literal value of 3, and then put a points 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, it will point b directly to the address of 3. In this way, a and b both point to 3 at the same time.

  It is important to note that this literal reference is not the same as a class object reference. Assuming that the references of two class objects point to an object at the same time, if an object reference variable modifies the internal state of the object, then the other object reference variable also immediately reflects the change. Conversely, modifying its value through a reference to the literal does not cause the value of another reference to the literal to change as well. 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, but will still be equal to 3. Inside the compiler, when it encounters a=4;, 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, changes in the value of a will not affect the value of b.

  The other is to wrap class data, such as Integer, String, Double and other classes that wrap the corresponding basic data types. These class data all exist in the heap. Java uses the new() statement to explicitly tell the compiler that it is dynamically created as needed at runtime, so it is more flexible, but the disadvantage is that it takes more time. 4. String is a special wrapper class data. That is, it can be created in the form of String str = new String("abc");, or it can be created in the form of String str = "abc"; (for comparison, before JDK 5.0, you never saw Integer i = 3; expression, because classes and literal values ​​are not common, except String. In JDK 5.0, this kind of expression is OK! Because the compiler performs the conversion of Integer i = new Integer(3) in the background) . The former is the normative class creation process, that is, in Java, everything is an object, and an object is an instance of a class, which is all created in the form of new(). Some classes in Java, such as the DateFormat class, can return a newly created class through the class's getInstance() method, which seems to violate this principle. actually not. This class uses the singleton pattern to return an instance of the class, but this instance is created inside the class through new(), and getInstance() hides this detail from the outside. Then why in String str = "abc"; does not create an instance through new(), does it violate the above principles? Actually no.

  5. Regarding the inner workings of String str = "abc". Java internally converts this statement into the following steps:

  (1) First define a variable named str that refers to an object of the String class: String str;

  (2) Find out whether there is an address with the value "abc" in the stack, if not, open an address with the literal value "abc", then create a new object o of the String class, and put the character of o The string value points to this address, and the referenced object o is noted on the stack next to this address. If there is already an address with the value "abc", look up the object o, and return the address of o.

  (3) Point str to the address of object o.

  It is worth noting that the string values ​​in the general String class are stored directly. But like String str = "abc"; in this case, the string value holds a reference to the data stored on the stack!

  In order to better illustrate this problem, we can verify it through the following codes.

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

  Note that we do not use str1.equals(str2); here, because this will compare two whether the values ​​of the strings are equal. The == sign, according to the JDK, returns true only if both references point to the same object. And what we want to see here is whether str1 and str2 both point to the same object.
The results show that the JVM created two references str1 and str2, but only created one object, and both references point to this object.

  Let's go a step further and change the above code to:

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

  This means that the change in assignment results in a change in the class object reference, and str1 points to another new object! And str2 still points to the original object. In the above example, when we change the value of str1 to "bcd", the JVM finds that there is no address where the value is stored in the stack, so it opens up this address and creates a new object whose string value points to this address.

  In fact, the String class is designed to be immutable. If you want to change its value, you can, but the JVM quietly creates a new object at runtime based on the new value, and then returns the address of this object to a reference to the original class. Although this creation process is completely automatic, it takes more time after all. In an environment that is more sensitive to time requirements, it will have certain adverse effects.

  Modify the original code:

String str1 = "abc";
String str2 = "abc";

str1 = "bcd";

String str3 = str1;
System.out.println(str3); //bcd

String str4 = "bcd";
System .out.println(str1 == str4);

  //true The reference to the object str3 points directly to the object pointed to by str1 (note that str3 does not create a new object). When str1 changes its value, create a String reference str4, and point to the new object created by str1 modifying the value. It can be found that str4 does not create a new object this time, thus realizing the sharing of data in the stack again.

  Let's look at the code below.

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

  creates two references. Two objects are created. The two references point to two different objects respectively.

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

  creates two references. Two objects are created. The two references point to two different objects respectively.

  The above two pieces of code show that as long as new() is used to create a new object, it will be created in the heap, and its string is stored separately, even if it is the same as the data in the stack, it will not be shared with the data in the stack. .

  6. The value of the data type wrapper class cannot be modified. Not only the value of the String class cannot be modified, but all data type wrapper classes cannot change the value inside it. 7. Conclusions and suggestions:

  (1) When we define a class in a format such as String str = "abc";, we always take it for granted that we create an object str of the String class. Worry about the trap! The object may not have been created! The only certainty is that a reference to the String class is created. Whether or not this reference points to a new object must be considered contextually, unless you explicitly create a new object via the new() method. Therefore, it is more accurate to say that we have created a reference variable str that points to an object of class String, and this object reference variable points to a String class whose value is "abc". Awareness of this can be helpful in troubleshooting hard-to-find bugs in programs.

  (2) Using the method of String str = "abc"; can improve the running speed of the program to a certain extent, because the JVM will automatically decide whether it is necessary to create a new object according to the actual situation of the data in the stack. For the code of String str = new String("abc");, new objects are created in the heap, regardless of whether their string values ​​are equal, whether it is necessary to create new objects, which increases the burden of the program. This idea should be the idea of ​​flyweight mode, but it is unknown whether the internal implementation of JDK applies this mode.

  (3) When comparing the values ​​in the wrapper class for equality, use the equals() method; when testing whether the references of the two wrapper classes point to the same object, use ==.

  (4) Due to the immutable nature of the String class, when the String variable needs to change its value frequently, the StringBuffer class should be considered to improve program efficiency.


Stack (stack): is a first-in, last-out data structure, usually used to save parameters and local variables in methods (functions).
In java, all basic types and reference types are stored in the stack. The survival of data in the stack The space is generally in the current scopes (that is, the area enclosed by {...}).

Heap (heap): is a memory space that can be dynamically applied (the linked list that records the free memory space is maintained by the operating system), in C The memory space generated by the malloc statement is in the heap.
In java, all objects constructed using new xxx() are stored in the heap. When the garbage collector detects that an object is not referenced, it will automatically destroy the object. Therefore, in theory, the living space of an object in java is not limited, as long as there is a reference type pointing to it, it can be used anywhere.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326560534&siteId=291194637