This article has been collected from the author of the open source JavaGuide: github.com/Snailclimb ([Java learning + interview guide] a cover of most Java programmers need to master the core knowledge) if you feel good, you might as well go to the Star, encourage!
Java memory area details
Unless otherwise specified, this is for the HotSpot VIRTUAL machine.
Write in the front
The basic problem
- Introducing the Java memory area (runtime data area)
- Java object creation process (5 steps, recommended to be able to write and know what the virtual machine does at each step)
- Two ways to access and locate objects (handle and direct pointer)
Expand the problem
- String class and constant pool
- Eight basic types of wrapper classes and constant pools
An overview of
For Java programmers, under the automatic memory management mechanism of virtual machine, there is no need to write delete/free operation for each new operation like C/C++ program developers, which is not prone to memory leakage and overflow problems. Because Java programmers have entrusted memory control to the Java virtual machine, memory leaks and spills can be a daunting task if you don’t know how the virtual machine is using memory.
Run-time data area
During the execution of Java programs, the Java VIRTUAL machine divides the memory it manages into different data areas. JDK.1.8 is slightly different from previous releases, as described below.
Before JDK 1.8:
JDK 1.8:
Thread private:
- Program counter
- The virtual machine stack
- Local method stack
Thread shared:
- The heap
- Methods area
- Direct memory (part of the non-runtime data area)
2.1 Program counter
A program counter is a small memory space that can be viewed as a line number indicator of the bytecode being executed by the current thread. The bytecode interpreter works by changing the value of this counter to select the next bytecode instruction to be executed. Branches, loops, jumps, exception handling, thread recovery and other functions depend on this counter.
In addition, in order to restore the thread to the correct execution position after switching, each thread needs to have an independent program counter, which does not affect each other and is stored independently. We call this kind of memory area “thread private” memory.
From the introduction above, we know that the program counter has two main functions:
- The bytecode interpreter changes the program counter to read instructions in turn, thus achieving control of the flow of code, such as sequential execution, selection, looping, exception handling.
- In the case of multiple threads, the program counter is used to keep track of where the current thread is executing, so that when the thread is switched back it can know where it was last run.
Note: The program counter is the only memory area that does not have an OutOfMemoryError, and its life cycle is created with the creation of a thread and dies with the end of the thread.
2.2 Java Virtual Machine Stack
Like program counters, the Java virtual machine stack is thread-private and has the same lifecycle as a thread. It describes the in-memory model of the execution of Java methods, and the data for each method call is passed through the stack.
Java memory can be roughly divided into Heap memory and Stack memory, where the Stack is now referred to as the virtual machine Stack, or the local variable scale part of the virtual machine Stack. (Actually, the Java virtual machine stack is made up of stack frames, and each stack frame has: local variable table, operand stack, dynamic link, method exit information.)
The local variable table mainly stores various data types known by the compiler (Boolean, byte, CHAR, short, int, float, long, double), object references (reference type, which is different from the object itself, may be a reference pointer to the object’s starting address. It may also point to a handle representing an object or other location associated with this object.
There are two types of Java virtual machine stack errors: StackOverFlowError and OutOfMemoryError.
- StackOverFlowError: If the memory size of the Java virtual machine stack does not allow dynamic scaling, a StackOverFlowError is thrown when the thread requests the stack depth beyond the current maximum depth of the Java virtual machine stack.
- OutOfMemoryError: An OutOfMemoryError is thrown if the memory size of the Java virtual machine stack allows dynamic expansion and the memory is exhausted when the thread requests the stack.
The Java virtual machine stack is also thread-private, with each thread having its own Java virtual machine stack that is created as a thread is created and dies as a thread dies.
Extension: So how do methods/functions get called?
Java stack can be used to analogy the data structure stack, the main content stored in the Java stack is the stack frame, each function call will have a corresponding stack frame is pushed into the Java stack, after each function call, there will be a stack frame is popped.
Java methods can return in two ways:
- The return statement.
- Throw an exception.
Either return method will cause the stack frame to be ejected.
2.3 Local method stack
This function is very similar to that of the virtual machine stack, except that the virtual machine stack performs Java methods (that is, bytecode) services for the virtual machine, while the Native method stack serves Native methods used by the virtual machine. Integrate the HotSpot VIRTUAL machine with the Java virtual machine stack.
When a local method is executed, a stack frame is also created on the local method stack to hold the local variable table, operand stack, dynamic link, and exit information for the local method.
StackOverFlowError and OutOfMemoryError occur when the stack frame is removed and memory is freed.
2.4 the heap
The largest chunk of memory managed by a Java virtual machine, the Java heap is an area of memory shared by all threads and created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and almost all object instances and arrays are allocated memory here.
The Java Heap is the primary area managed by the Garbage collector and is therefore also known as the Garbage Collected Heap. From the point of view of garbage collection, the Java heap can be subdivided into: new generation and old generation: Eden space, From Survivor, To Survivor space, etc. The purpose of further partitioning is to better reclaim memory, or to allocate memory faster.
Prior to JDK 7 and JDK 7, heap memory was generally divided into the following three parts:
- Young Generation
- Old Generation
- Permanent Generation
After JDK 8, the method area (HotSpot’s permanent generation) was completely removed (already in JDK1.7) in favor of the meta space, which uses direct memory.
The Eden region shown in the figure above and the two Survivor regions belong to the Cenozoic era (the two Survivor regions are named from and to in order to distinguish them), and the middle layer belongs to the old era.
In most cases, the object will be allocated in Eden first. After a Cenozoic garbage collection, if the object is still alive, it will enter S0 or S1 and its age will be increased by 1(the initial age of the object becomes 1 after Eden ->Survivor). When it reaches a certain age (15 by default), it is promoted to the old age. The age threshold for the object to be promoted to the old age can be set by using -xx :MaxTenuringThreshold.
Fix (issue552) : “As Hotspot traverses all objects, it accumulates the size it occupies from small to large, and when it accumulates a certain age that exceeds half of the survivor zone, it takes that age and a smaller value of MaxTenuringThreshold as the new promotion age threshold.”
The code for dynamic age calculation is as follows
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { //survivor_capacity is the size of survivor space size_t desired_survivor_size = (size_t) ((((double) survivor_capacity)*TargetSurvivorRatio)/100); size_t total = 0; uint age = 1; while (age < table_size) { total += sizes[age];// Sizes array is the object size of each age group if (total > desired_survivor_size) break; age++; } uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold; . }Copy the code
An OutOfMemoryError is the most common in the heap, and can take several forms, such as:
- OutOfMemoryError: GC Overhead Limit Exceeded: This error occurs when the JVM spends too much time performing garbage collection and can only reclaim too little heap space.
java.lang.OutOfMemoryError: Java heap space
: Is thrown if there is not enough space in heap memory to hold the newly created object when it is being createdjava.lang.OutOfMemoryError: Java heap space
Error. (Has nothing to do with the native physical memory, and you configure the memory size!)- .
2.5 method area
The method area, like the Java heap, is an area of memory shared by individual threads to store data such as class information that has been loaded by the virtual machine, constants, static variables, code compiled by the just-in-time compiler, and so on. Although the Java Virtual Machine specification describes the method area as a logical part of the Heap, it has an alias called non-heap, which is supposed to distinguish it from the Java Heap.
Method regions are also known as permanent generations. A lot of people confuse method regions with permanent generations, so I’ve looked in the literature.
2.5.1 Relationship between method area and permanent generation
The Java Virtual Machine Specification defines the concept of a method area and what it does, not how to implement it. Then, the implementation of the method area must be different on different JVMS. The relationship between a method area and a persistent generation is much like the relationship between an interface and a class in Java that implements the interface, and a persistent generation is the HotSpot VIRTUAL machine’s way of implementing the method area in the VIRTUAL machine specification. In other words, persistent generation is the concept of HotSpot, method area is defined in the Java virtual machine specification, is a specification, and persistent generation is an implementation, one is a standard and one is an implementation, other virtual machine implementations do not have the term persistent generation.
2.5.2 Common Parameters
Before the permanent generation was completely removed in JDK 1.8, the following parameters were used to adjust the method area size
-XX:PermSize=N // The method area (permanent generation) initial size
-XX:MaxPermSize=N / / method area (permanent) maximum size, more than this value will throw an OutOfMemoryError: Java. Lang. OutOfMemoryError: PermGen
Copy the code
Garbage collection is relatively rare in this area, but data is not “permanent” once it enters the method area.
In JDK 1.8, the method area (HotSpot’s permanent generation) was completely removed (already in JDK1.7) in favor of the meta space, which uses direct memory.
Here are some common parameters:
-XX:MetaspaceSize=N // Set the initial (and minimum) size of Metaspace
-XX:MaxMetaspaceSize=N // Set the maximum Metaspace size
Copy the code
A big difference from the permanent generation is that, if the size is not specified, the virtual machine will use up all available system memory as more classes are created.
2.5.3 Why is PermGen replaced with MetaSpace?
- The entire permanent generation has a fixed size cap set by the JVM itself, which cannot be adjusted, while the metaclass uses direct memory and is limited by the native available memory. Although the metaclass may still overflow, it occurs less often than before.
Get the following error: when you yuan space overflow Java. Lang. OutOfMemoryError: MetaSpace
You can set the maximum meta-space size using the -xx: MaxMetaspaceSize flag. The default value is Unlimited, which means it is limited only by system memory. -xx: MetaspaceSize Resize flag Defines the initial size of the metspace. If this flag is not specified, Metaspace will dynamically resize according to the application requirements at run time.
-
MaxPermSize does not control how much class metadata is loaded, but the actual available space of the system controls, so that more classes can be loaded.
-
JRockit never had such a thing as a permanent generation when merging HotSpot and JRockit code in JDK8. There is no need to set up such a permanent generation after merging.
2.6 Runtime constant pool
The runtime constant pool is part of the method area. In addition to the description of the Class version, fields, methods, interfaces, etc., the Class file also contains constant pool information (used to store various literal and symbolic references generated at compile time).
Since the runtime constant pool is part of the method area and is naturally limited by the method area memory, OutOfMemoryError is thrown when the constant pool can no longer claim memory.
JDK1.7 and later JVMS have moved the runtime constant pool out of the method area, creating an area in the Java Heap to house the runtime constant pool.
Blog.csdn.net/wangbiao007…
2.7 Direct Memory
Direct memory is not part of the virtual machine’s run-time data area, nor is it defined in the virtual machine specification, but it is frequently used. It may also cause an OutOfMemoryError.
The NIO(New Input/Output) class added in JDK1.4 introduces an I/O mode based on Channel and Buffer, which can directly allocate out-of-heap memory using Native function library. It then operates through a DirectByteBuffer object stored in the Java heap as a reference to this memory. This can significantly improve performance in some scenarios because it avoids copying data back and forth between the Java heap and Native heap.
Native direct memory allocation is not limited by the Java heap, but since it is memory, it is limited by the total native memory size and processor addressing space.
HotSpot VIRTUAL Machine object explorer
With the introduction above we have a general idea of the virtual machine memory, let’s take a detailed look at the HotSpot VIRTUAL machine in the Java heap object allocation, layout and access process.
3.1 Object Creation
Here is the Java object creation process. I recommend writing it out by ear and knowing what you are doing at each step.
Step1: class loading check
When a virtual machine arrives at a new instruction, it first checks to see if the instruction’s arguments locate the symbolic reference to the class in the constant pool, and to see if the symbolic reference represents a class that has been loaded, parsed, and initialized. If not, the corresponding class loading process must be performed first.
Step2: Allocate memory
After the class load check passes, the virtual machine next allocates memory for the new objects. The size of memory required by an object is determined after the class is loaded, and the task of allocating space for an object is equivalent to dividing a certain size of memory from the Java heap. There are two types of allocation: “pointer collision” and “free list”, which allocation is determined by whether the Java heap is clean, which in turn is determined by whether the garbage collector used has collation capabilities.
Two ways to allocate memory :(supplementary content, need to master)
The choice between the two approaches depends on whether the Java heap memory is tidy. Whether the Java heap memory is clean depends on whether the GC collector’s algorithm is “mark-clean” or “mark-tidy” (also known as “mark-compress”). Notably, the copy-algorithm memory is clean as well
Memory allocation concurrency problem
There is a very important issue when creating objects, is thread safety, because in the actual development process, object creation is very frequent things, as a virtual machine, must ensure that thread safety, generally speaking, virtual machines use two ways to ensure thread safety:
- CAS+ Retry on failure: CAS is an implementation of optimistic locking. Optimistic locking is when an operation is performed each time without locking, assuming no conflicts, and then retry until it succeeds if it fails because of conflicts. The CENTRAL Authentication Service (CAS) configuration fails to retry to ensure atomicity of update operations.
- TLAB: each thread is allocated a block of memory in Eden area in advance. When THE JVM allocates memory to objects in the thread, it first allocates memory in TLAB. When the object is larger than the remaining memory in TLAB or the memory in TLAB is exhausted, the CAS is used for memory allocation
Step3: initialize a zero value
After the memory allocation is complete, the VIRTUAL machine needs to initialize the allocated memory space to zero values (excluding the object header). This step ensures that the instance fields of the object can be used in Java code without assigning initial values, and the program can access the zero values corresponding to the data types of these fields.
Step4: set the object header
After initializing the zero value, the virtual machine sets up the object as necessary, such as which class the object is an instance of, how to find the metadata information about the class, the object’s hash code, the object’s GC generation age, and so on. This information is stored in the object header. In addition, the object header can be set differently depending on the running status of the VM, for example, whether biased locking is enabled.
Step5: execute the init method
From the virtual machine’s point of view, a new object has been created, but from the Java program’s point of view, object creation has just begun, the
method has not yet been executed, and all fields are still zero. So, in general, the new instruction is followed by the
method, which initializes the object as the programmer wishes, and a usable object is fully generated.
3.2 Memory layout of objects
In the Hotspot VIRTUAL machine, the layout of objects in memory can be divided into three areas: object headers, instance data, and aligned padding.
Hotspot virtual machine object consists of two pieces of information, the first part of its own runtime data are used to store objects (hash code, GC generational age, lock status flag, etc.), the other part is a pointer type, namely the object pointer to its class metadata, virtual machine this object is determined by the pointer to the instance of the class.
The instance data part is the valid information that the object actually stores and the content of various types of fields defined in the program.
The alignment padding part is not necessarily there and has no special meaning. It just serves as a placeholder. Because the Hotspot VIRTUAL machine’s automatic memory management system requires that the object’s starting address be an integer multiple of 8 bytes, in other words, the object’s size must be an integer multiple of 8 bytes. The object header is exactly a multiple (1 or 2) of 8 bytes, so when the object instance data part is not aligned, it needs to be filled by alignment.
3.3 Object Access Location
Objects are created to use objects, and our Java program operates on specific objects on the heap using reference data on the stack. The object access mode is determined by the VM. Currently, there are two main access modes: ① Handle and ② direct pointer:
- Handle: If handle is used, a chunk of memory will be allocated to the Java heap as a handle pool. Reference stores the address of the handle of the object, and the handle contains the specific address information of the instance data and type data of the object.
- Direct Pointers: If direct pointer access is used, then the layout of the Java heap object must consider how to place information about the access type data, and the direct stored in Reference is the address of the object.
Both object access methods have their own advantages. The biggest benefit of using handles for access is that reference stores a stable handle address and only changes the instance data pointer in the handle when the object is moved. Reference itself does not need to be modified. The biggest advantage of using direct pointer access is fast speed, it saves the time cost of a pointer location.
Key supplementary content
4.1 String classes and constant pools
There are two ways to create a String:
String str1 = "abcd";// First check if there is "abcd" in the string constant pool. If there is no "abcd" in the string constant pool, create one. Then str1 points to the object in the string constant pool.
String str2 = new String("abcd");// Create a new object in the heap
String str3 = new String("abcd");// Create a new object in the heap
System.out.println(str1==str2);//false
System.out.println(str2==str3);//false
Copy the code
There is a difference between these two different creation methods.
- The first way is to get an object in a constant pool;
- The second way is to create a new object directly in the heap memory space.
Remember that whenever you use the new method, you need to create a new object.
Give everyone a figure should be more easy to understand, image: www.journaldev.com/797/what-is… :
String constant pools are special. It can be used in two main ways:
- Strings declared directly in double quotes are stored directly in the constant pool.
- If a String object is not declared in double quotes, you can use the intern method provided by String. String. Intern () is a Native method that returns a reference to a String in the constant pool if the runtime constant pool already contains a String equal to the String. If not, the way to do this prior to JDK1.7 (but not including 1.7) is to create a String with the same content as the String in the constant pool and return a reference to the String created in the constant pool, and the way to do this after JDK1.7 is to record a reference to the String in the constant pool and return the reference.
String s1 = new String("Computer");
String s2 = s1.intern();
String s3 = "Computer";
System.out.println(s2);/ / computer
System.out.println(s1 == s2);//false, because one is a String in the heap and the other is a String in the constant pool,
System.out.println(s3 == s2);//true, because both are strings in the constant pool
Copy the code
String concatenation:
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";// Objects in the constant pool
String str4 = str1 + str2; // Create a new object on the heap
String str5 = "string";// Objects in the constant pool
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
Copy the code
Avoid concatenating multiple strings, as this recreates the object. If you need to change strings, you can use StringBuilder or StringBuffer.
4.2 String s1 = new String(” ABC “); How many string objects does this sentence create?
One or two strings will be created. If the string constant “ABC” already exists in the pool, only one string constant “ABC” is created in the heap space. If there is no string constant “ABC” in the pool, it will be created first in the pool and then in the heap space, so a total of 2 string objects will be created.
Validation:
String s1 = new String("abc");// Heap memory address value
String s2 = "abc";
System.out.println(s1 == s2);// Print false because one is heap memory and the other is constant pool memory, so the two are different.
System.out.println(s1.equals(s2));/ / output true
Copy the code
Results:
false
true
Copy the code
4.3 Eight basic types of wrapper classes and constant pools
- Most of the basic types of Java wrapper class implements the constant pool technology, namely, Byte, Short, Integer, Long, Character, and Boolean; These five wrapper classes create the corresponding type of cached data for the value [-128,127] by default, but new objects are still created beyond this range. Why set cache to range [-128,127]? (See Issue /461) Tradeoffs between performance and resources.
- The wrapper class Float,Double, for two floating-point types, does not implement constant pooling technology.
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);/ / output true
Integer i11 = 333;
Integer i22 = 333;
System.out.println(i11 == i22);/ / output is false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);/ / output is false
Copy the code
Integer cache source code:
/** * This method will always cache values in the range -128 to 127, including endpoints, and can cache other values outside this range. * /
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Copy the code
Application Scenarios:
- The Integer i1 = 40; I1 = integer.valueof (40); i1= integer.valueof (40); To use objects in the constant pool.
- Integer i1 = new Integer(40); In this case, a new object is created.
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);/ / output is false
Copy the code
Integer is a richer example:
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
System.out.println("i1=i2 " + (i1 == i2));
System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
System.out.println("i1=i4 " + (i1 == i4));
System.out.println("i4=i5 " + (i4 == i5));
System.out.println("i4=i5+i6 " + (i4 == i5 + i6));
System.out.println("40=i5+i6 " + (40 == i5 + i6));
Copy the code
Results:
i1=i2 true
i1=i2+i3 true
i1=i4 false
i4=i5 false
i4=i5+i6 true
40=i5+i6 true
Copy the code
Explanation:
Statement i4 == i5 + i6, since the + operator does not apply to Integer objects, first i5 and i6 are automatically unboxed, adding the values, i4 == 40. Then the Integer object cannot be directly compared to a numeric value, so i4 automatically unboxes itself to int 40, and finally the statement is converted to 40 == 40 for numeric comparison.
reference
- Understanding the Java Virtual Machine in Depth: Advanced JVM Features and Best Practices (2nd Edition)
- Real Java Virtual Machine
- Docs.oracle.com/javase/spec…
- www.pointsoftware.ch/en/under-th…
- Dzone.com/articles/jv…
- Stackoverflow.com/questions/9…
- In-depth analytical String#interntech.meituan.com/2014/03/06/…
The public,
If you want to follow my updated articles and shared dry goods in real time, you can follow my official account.
“Java interview assault “: derived from this document designed for the interview and born of the “Java interview assault” V2.0 PDF version of the public number background reply “Java interview assault “can be free!
Necessary learning resources for Java engineers: Some Java engineers commonly use learning resources public account background reply keyword “1” can be free of routine access.
Open Source Project Recommendation
Other open source projects recommended by the authors:
- JavaGuide: A Java learning + Interview Guide that covers the core knowledge that most Java programmers need to master.
- Springboot-guide: A Spring Boot tutorial for beginners and experienced developers.
- Advancer-advancement: I think there are some good habits that technical people should have!
- Spring-security-jwt-guide: Start from Scratch! Spring Security With JWT (including permission validation) backend part of the code.
The public,
Amway ali cloud double 12 activities, 1 nuclear 2g as long as 89 a year, pull wave wool, feeling very cool, but the lowest concessions are new people to enjoy, I am with my girlfriend’s account to buy, no girlfriend, EMM….. , can consider the relatives.