Java Memory Allocation

Source: Internet
Author: User

Java Memory Allocation

This article will introduce the principle of Java memory allocation in detail from a simple perspective to help beginners learn Java more easily. There are many such articles on the Internet, but most of them are fragmented. This article will give readers a systematic introduction from the perspective of cognitive processes.

Before getting started, you must first know that the Java program runs on the JVM (Java Virtual Machine (JVM), which can be understood as a bridge between the Java program and the operating system, JVM implements the platform independence of Java. This shows the importance of JVM. Therefore, when learning about the Java memory allocation principle, you must keep in mind that all this is done in the JVM. JVM is the basis and premise of the memory allocation principle.

To put it simply, a complete Java program running process involves the following memory areas:

L register: Virtual registers inside JVM. The access speed is very fast and the program cannot be controlled.

L stack: stores local variable values, including: 1. Stores basic data type values; 2. Saves class instances, that is, references (pointers) of heap objects ). It can also be used to save the frame when loading the method.

L heap: used to store dynamically generated data, such as new objects. Note that the created object only contains the member variables and does not include the member methods. Because objects of the same class have their own member variables and are stored in their respective stacks, but they share the methods of this class, instead of copying the member methods once every time an object is created.

L constant pool: JVM maintains a constant pool for each loaded type. The constant pool is an ordered set of constants used for this type. Including direct constants (basic type, String) and symbol references to other types, methods, and fields (1 ). The data in the pool is accessed through indexes like the array. Because the constant pool contains all types of symbolic references to other types, methods, and fields, the constant pool plays a core role in the dynamic link of Java. The constant pool exists in the heap.

L code segment: used to store the source code read from the hard disk.

L Data Segment: used to store static members defined by static.

The following figure shows the memory representation:



This section describes the Java memory allocation. Next, we will explain in detail how the Java program runs in the memory through examples. (Note: We reference the J2SE courseware prepared by Jack Ma from shangxuanxiang, the right side of the figure is the program code, and the left side is the memory allocation. I will add comments one by one ).

Prerequisites:


1. A Java file, as long as there is a main entry method, we think it is a Java program and can be compiled and run separately.

2. Both common variables and referenced variables (commonly called instances) can be used as local variables and they can all appear in the stack. However, variables of the common type directly store their corresponding values in the stack, and variables of the reference type store a pointer to the heap zone. Through this pointer, you can find the object corresponding to this instance in the heap area. Therefore, common type variables only occupy one block of memory in the stack area, and referenced type variables occupy one block of memory in the stack and heap areas.

Example:



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

2. Create a date variable of the int type. Because it is of the basic type, store the value 9 corresponding to the date directly in the stack.

3. Create two BirthDate instances d1 and d2, and store corresponding pointers to their respective objects in the stack. They call construction methods with parameters during instantiation, so the object has a custom initial value.



Call the change1 method of the test object and use date as the parameter. When JVM reads this code, it detects that I is a local variable, so it places I in the stack and assigns the value of date to I.



Assign 1234 to I. This is a simple step.



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



Call the change2 method of the test object, with instance d1 as the parameter. JVM detects that the parameter B in the change2 method is a local variable and immediately adds it to the stack. Because it is a reference type variable, the pointer in d1 is saved in B, in this case, B and d1 point to the object in the same heap. The pointer is passed between B and d1.



In the change2 method, a BirthDate object is instantiated and assigned to B. The internal execution process is: a new object is added in the heap area, and the pointer of this object is saved in the corresponding space of B in the stack. At this time, instance B no longer points to the object pointed to by instance d1, however, the object to which instance d1 is directed does not change, which cannot affect d1.



After the change2 method is executed, the stack space occupied by local referenced variable B is immediately released. Note that the stack space is only released and the heap space needs to be automatically recycled.



Call the change3 method of the test instance and take instance d2 as the parameter. Similarly, JVM allocates space for local reference variable B in the stack and stores the pointer in d2 in B. At this time, d2 and B point to the same object. The setDay method of instance B is called to call the setDay method of the object pointed to by d2.



Calling the setDay method of instance B affects d2 because the two point to the same object.



After the change3 method is executed, release the local reference variable B immediately.


The above is the general situation of memory allocation during Java program running. In fact, there is nothing. It is easy to master the idea. There are only two types of variables: basic type and reference type. Both of them are local variables in the stack. The basic types store values directly in the stack. The reference type only saves one pointer to the heap zone, and the real object is in the heap. When a parameter is set as a basic type, the value is directly transferred, and the pointer is passed as a reference type.

Summary:


1. Identify what an instance is and what an object is. Class a = new Class (); at this time, a is called an instance, but cannot be said that a is an object. The instance is in the stack, and the object is in the heap. In fact, the instance is operated indirectly through the instance pointer. Multiple instances can point to the same object.

2. Data in the stack and data destruction in the stack are not synchronized. Once the method ends, partial variables in the stack are destroyed immediately, but objects in the heap are not necessarily destroyed. Because other variables may point to this object until no variable in the stack points to the object in the heap, it will not be destroyed immediately, it can be destroyed only after the garbage collection scan.

3. The above stacks, stacks, code segments, data segments, and so on are all relative to applications. Each application corresponds to a unique JVM instance, and each JVM instance has its own memory region, which does not affect each other. All threads share the memory. The stack and heap mentioned here are both overall concepts, and these stacks can also be subdivided.

4. The member variables of the class are different in different objects and all have their own storage space (the member variables are in the objects in the heap ). The class method is shared by all objects of the class. Only one set of objects is pushed to the stack when the method is used. If the method is not used, the memory is not occupied.

The above analysis only involves the stack and heap, and there is also a very important memory area: constant pool, which often has some inexplicable problems. The above figure shows what the constant pool does, and there is no need to understand it deeply. Just remember that it maintains a constant of loaded classes. The following describes the features of the constant pool with examples.

Prerequisites:


The packaging class of the basic type and basic type. The basic types include byte, short, char, int, long, and boolean. The basic types of packages are Byte, Short, Character, Integer, Long, and Boolean. Be case sensitive. The difference between the two is: the basic type is reflected in the program is a common variable, the basic type of packaging class is a class, reflected in the program is a reference variable. Therefore, the two are stored in different memory locations: the basic type is stored in the stack, while the basic type is stored in the heap. The preceding packaging classes all implement the constant pool technology, while the other two floating point number types do not. In addition, the String type also implements the constant pool technology.


Instance:

[Java] view plaincopy

  1. ?
    123456789101112131415161718192021222324252627 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:

[Java] view plaincopy

  1. ?
    123456 i=i0    truei1=i2   truei1=i2+i3        truei4=i5   falsei4=i5+i6        trued1=d2   false

 

Result Analysis:

1. I and i0 are common type (int) variables, so data is directly stored in the stack, and the stack has a very important feature: Data in the stack can be shared. When we define int I = 40; and then define int i0 = 40; at this time, it will automatically check whether there is 40 data in the stack. If there is, i0 will direct to 40 of I, no new 40 will be added.

2. i1 and i2 are both reference types. the pointer is stored in the stack because Integer is a packaging class. Since the Integer packaging class implements the constant pool technology, the i1 and i2 40 are obtained from the constant pool and all point to the same address, so i1 = 12.

3. obviously, this is an addition operation. Java's mathematical operations are carried out in the stack. Java will automatically split i1 and i2 into integers, therefore, i1 is equivalent to i2 + i3.

4. i4 and i5 are both reference types. the pointer is stored in the stack because Integer is a packaging class. However, since they are all new, they no longer look for data from the constant pool, but new objects from the heap, and then save the pointers pointing to objects respectively, therefore, i4 and i5 are not equal because they have different pointers and direct to different objects.

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

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

Summary:

1. the above several basic types of packaging classes all implement the constant pool technology, but they maintain only constants in the range [-128 to 127]. If the constant value exceeds this range, the object will be created from the heap and will not be retrieved from the constant pool. For example, if you change the preceding example to Integer i1 = 400; Integer i2 = 400;, it is obvious that the value exceeds 127. If you cannot obtain a constant from the constant pool, you must create a new Integer object from the heap, in this case, i1 and i2 are not equal.

2. the String type also implements the constant pool technology, but it is slightly different. String type is used to check whether there is a corresponding String in the constant pool. If yes, it is obtained. If no, the current String is added.

Everything that involves the principle of memory is generally a broad and profound field. Do not listen to the words of the family and read more articles. I am only an analysis here, and there are still a lot of tricks in it, so I leave it for readers to explore and think. I hope this article will help you!

Footer:

(1) A symbolic reference, as its name implies, is a symbol. It is resolved only when it is used. If you are familiar with linux or unix systems, you can regard this symbolic reference as a soft link to a file. When you use this soft link, it will actually parse it and expand it to find the actual file.

There are many discussions on symbolic references at the class loading level. The source code level is just a formal discussion.

When a class is loaded, the symbolic references of other classes used by the class are stored in the constant pool. during actual code execution, when a class is first encountered, JVM expands the symbolic reference of the class in the constant pool and converts it to a direct reference. In this way, the JVM will no longer parse the class next time it encounters the same type, directly use this resolved direct reference.

In addition to the symbolic references in the above class loading process, for the source code level, it is to identify whether some data in the Code belongs to the symbolic reference or direct reference according to the referenced parsing process, for example, System. out. println ("test" + "abc"); // The result is equivalent to a direct reference. Assume that a Strings = "abc"; System. out. println ("test" + s); // The effect here is equivalent to a symbolic reference, that is, to parse s, which is equivalent to a symbolic link of "abc, that is to say, during compilation, the class file does not directly show s, but this s is regarded as a symbol. This will be opened only when the actual code is executed.

References:

Java Memory Allocation Research: http://www.blogjava.net/Jack2007/archive/2008/05/21/202018.html

Java constant pool detailed explanation of a relatively painful interview questions: http://www.cnblogs.com/DreamSea/archive/2011/11/20/2256396.html

Jvm constant pool: http://www.cnblogs.com/wenfeng762/archive/2011/08/14/2137820.html

Java core Java memory allocation principle: http://developer.51cto.com/art/201009/225071.htm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.