JVM series (1): Java memory area analysis, jvmjava
As a programmer, it is far from enough to know how to use it. At least, you need to know why it can be used, that is, what we call the underlying layer.
So what is the underlying layer? I don't think this can be generalized. In my current knowledge: for Web developers, TCP/IP, HTTP, and other protocols may be the underlying layer. For C and C ++ programmers, memory, pointer, and so on may be the underlying thing. For Java developers, the JVM where your Java code runs may be something you need to understand and understand.
I will study JVM with you over the next period of time. For details, refer to "deep understanding of Java VM: JVM advanced features and Best Practices" (version 2). Thank you.
This is the first article in the series, which describes
Java memory ZoneThat is, how data is stored on a virtual machine.
I. runtime data area
Data is divided into two parts: one part is shared by all threads, and the other part is private to each thread. The data area shared by the thread includes the method area and heap. The private data area of the thread includes the Virtual Machine stack, local method stack, and program counter. As shown in:
(Images are from the online library)
We will introduce these regions as follows:
1. Program counters
A small memory space can be seen as the row number indicator of the bytecode executed by the current thread.
If the thread is executing a JAVA method, the counter value is the address of the currently executed VM bytecode instruction; if the Native method is being executed, the counter value is empty.
This memory region is the only region that never has an OutOfMemoryError.
2. Virtual Machine Stack
The thread is private, and its lifecycle is the same as that of the thread. Describes the Memory Model of Java method execution. Each method creates a stack frame during execution to store information such as the local variable table, operand stack, dynamic link, and method exit. The process from calling to completion of each method corresponds to the process of loading a stack frame into the stack to the stack. Local variable table: the local variable table stores the basic data types (8 types, boolean, etc.) and object references (reference pointers pointing to the start address of the object, or point to a handle representing the object, or other locations related to the object), returnAddress type (pointing to the address of the bytecode instruction ). The memory space required by the local variable table is allocated during the compilation period. When you enter the method, the size of the local variable space that needs to be allocated for this method in the frame is completely determined and will not change during the runtime.
The local variable table may have two types of exceptions: If the stack depth requested by the thread is greater than the depth allowed by the virtual machine, an StackOverFlowError exception is thrown; if the Virtual Machine stack can be dynamically expanded (most virtual machines can ), if you cannot apply for sufficient memory during expansion, an OutOfMemory exception will be thrown.
3. Local method Stack
Similar to the Virtual Machine stack, the difference between them is that the virtual machine stack executes the Java method (also known as bytecode) service for the virtual machine, and the local method stack serves the Native method used by the virtual machine. StackOverFlowError and OutOfMemoryError are also thrown.
4. Java heap
For most applications, Java heap is the largest memory managed by Java virtual machines. The Java heap is shared by all threads and is created when the VM is started. The only purpose of this memory area is to store object instances. Memory is allocated here for almost all object instances (and arrays.
Java heap is the main area of the garbage collector management, so it is often used as a GC heap. The Java heap can be in physically discontinuous memory space, as long as it is logically continuous. In implementation, it can be fixed or expandable. If the heap does not have memory for instance allocation and the heap cannot be expanded, an OutOfMemoryError will be thrown.
5. Method Area
All threads are shared to store data such as class information, constants, static variables, and compiled code in the real-time editor loaded by virtual machines. Although this region is called "permanent generation", there is still memory recycling in this region, mainly for the collection of constant pools and the uninstallation of types. The method area also throws an OutOfMemoryError.
Runtime frequent volume pool: Part of the method area. In addition to the description information such as the version, field, method, and interface of the Class, the Class file also has a constant pool, which is used to store various literal quantities and symbol references generated during the compilation period, after the class is loaded, this part of content enters the runtime pool of the method area.
6. Direct Memory
Direct Memory is not part of the data zone during virtual machine running, but this part of memory is also frequently used, which may also cause an OutOfMemoryError exception.
JDK1.4 adds the NIO (New Input/Out) class and introduces an I/O Method Based on channels and buffers. You can use the Native function library to directly allocate off-heap memory, then, a DirectByteBuffer object stored in the Java heap is used as a reference to the memory. This can improve performance in some scenarios and avoid replicating data back and forth between Java heap and Native heap.
The total memory of the Local Machine and the addressing space of the processor (for example, if the processor is 32-bit, then the content you can access through the address is 2 ^ 32, that is, 4G, therefore, the maximum memory you can use is 4 GB), and an OutOfMemoryError is thrown.
Ii. Object creation, layout and access
After knowing what is stored in the memory, we naturally want to learn more about other details in the VM memory. For example, how to create, layout, and access. Taking the most popular hot spot Virtual Machine and common memory area Java heap as an example, we will discuss the entire process of object allocation, layout and access.
1. Create an object. Of course, the new command is used to create an object. When a VM encounters a new command, it first checks whether the parameter of this command can locate a Class symbol reference in the constant pool, check whether the referenced class has been loaded, parsed, and initialized. That is
Step 1: Check whether the new class is loaded by the Virtual Machine. If the class is not loaded, the corresponding class loading process must be executed first.(This will be detailed in future articles)
Then allocate memory for the new object.The size of the memory required by the object can be completely determined after the class is loaded. There are two ways to allocate memory:
Pointer collision: If the memory in the Java heap is absolutely regular, the memory used is put on one side, the idle memory is put on the other side, and a pointer in the middle is used as the indicator of the demarcation point, the memory allocation is just to move the pointer to the idle space to the same distance as the object size.
Idle list:If it is not regular, the virtual machine needs to maintain a list to record which memory blocks are available. When allocated, find a large enough space from the list and divide it into the object instance, and update the records in the list.
In addition to how to divide the available space, you also need to consider
Thread security issues when modifying pointers. It may occur that the memory is being allocated to object A, the pointer has not been modified, and object B uses the original pointer to allocate memory at the same time. There are two solutions to this problem:
Synchronize the actions for allocating memory space:CAS + retry upon failure ensures the atomicity of the update operation (what is CAS: compare-and-wwap. Principle: I think location V should contain the value A. if it contains the value, place location B. Otherwise, do not change the location, only tell me the current value of this location. Refer to this article: Analysis of CAS Principles)
The memory allocation action is divided into different spaces by thread:Each thread allocates a small block of memory in advance in the Java heap, which is called the local thread allocation buffer (TLAB). which thread needs to allocate memory is allocated on its own TLAB, if TLAB is used up and a new TLAB is assigned, the synchronization lock is added.
After the memory allocation is complete, the virtual machine needs to initialize the allocated memory space to a zero value.If you use TLAB, you can also proceed to TLAB allocation in advance. This step ensures that the instance fields of the object can be directly used in Java code without initial values. The program can access the zero value corresponding to the Data Types of these fields.
Next, you need to set the object.For example, which class is the object, how can I find the metadata information of the class, the hash of the object, and the GC age of the object,
The information is stored in the object header.Finally, the execution depends on the programmer's wishes.
.
2. Memory layout of Objects
It can be divided into three areas: object header, instance data, and alignment filling.
Object HeaderContains two parts: the first part is used to store the data during running of the object, such as hash, GC generational age, lock status mark, lock held by the thread, biased thread ID, biased timestamp, etc. The data in 32-bit and 64-bit virtual machines are 32-bit and 64-bit, respectively, called Mark Word. This part of data is too large to exceed the record limit, so it is designed as a non-fixed data structure to store as much information as possible in a very small space. (Based on Different flag spaces, its data represents different meanings .) Another part of the object header is the type pointer pointing to its class metadata (metadata is the data about the data). The VM uses this pointer to determine the instance of the class of the object.
Instance dataSome are the valid information that the object actually stores, and are also the various types of field content defined in the Code. Both inherited from the parent class and defined in the subclass must be recorded.
Alignment FillingIt does not necessarily exist. It only acts as a placeholder. The Automatic Memory Management System of HotSpot requires that the initial address of the object must be an integer multiple of 8 bytes. Therefore, when the data part of the object instance is not aligned, it must be filled with alignment.
3. Currently, the mainstream access methods for Object Access and locating are handle and direct pointer. (The handle can be understood as a channel for indirect object access .)
Handle usage:The Java heap divides a piece of memory into a handle pool, and the reference in the stack points to the handle address of the object. The handle contains the specific address information of the object instance data and type data respectively.
(Images are from the online library)
Direct pointer usage:The object address is stored in reference.
(Images are from the online library)
These two methods
Advantages: Use
Handle accessThe biggest benefit is that
StabilityWhen an object is moved (it is common to move the object during garbage collection), it only changes the instance data pointer in the handle, and the reference itself does not need to be modified. Use
Direct pointer accessThe biggest benefit is
FastSaves the time overhead of a pointer location.
Iii. Exception Generation Analysis
1. Java Heap Overflow
As long as you constantly create objects and ensure that there is an accessible path between GC and the objects, the garbage collection mechanism does not clear these objects, the memory overflow exception occurs when the number of objects reaches the maximum heap capacity limit.
To solve this problem, we usually analyze the heap dump snapshot using the memory image analysis tool to determine whether the memory object is necessary (that is, whether it is a memory leak or a memory overflow ). If yes
Memory leakageYou can use a tool to view the reference chain of the leaked object to GC Roots, and locate the location of the leaked code more accurately. If yes
Memory Overflow, You can increase the VM heap parameters, or check whether some objects have a long life cycle from the code.
2. Virtual Machine stack and local method Stack Overflow
If the stack depth requested by the thread is greater than the maximum depth allowed by the Virtual Machine stack, an StackOverflowError error is thrown. If the VM cannot apply for sufficient memory space when expanding the stack, an OutOfMemoryError error is thrown.
When a large number of local variables are defined and the length of the local variable table in the method frame is increased to the maximum depth allowed by the stack, StackOverflowError is thrown. In the case of a single thread, it is difficult to throw an OutOfMemoryError exception. Because when you reach the maximum stack depth, the memory space is generally not used up.
In the case of multiple threads, a new thread is constantly created, and new variables are constantly created in the new thread, which may throw an OutOfMemoryError.
3. Method zone and runtime constant pool overflow
String. intern () is a native method. Its function is to return a String object representing the String in the pool if the String constant pool already contains a String equal to this String object, otherwise, add the String contained in this String object to the constant pool and return a reference to this String object. In JDK1.6 and earlier versions, because the constant pool is allocated for a permanent generation, if the constant intern occurs, an OutOfMemoryError error is thrown. JDK1.7 is not thrown.
Method overflow: A class must be recycled by the garbage collector, and the judgment conditions are harsh. In applications that frequently generate a large number of classes dynamically, special attention should be paid to the collection of classes. For example, dynamic language, a large number of JSP applications, or applications that dynamically generate JSP files (JSP needs to be compiled into Java classes during the first run), OSGi-based applications (even the same class file, loaded by different loaders is also considered as different classes. But I have no research on OSGi. I will study it later ).