- The JVM source
Memory is a very important system resource. It is the intermediate warehouse and bridge between hard disk and CPU, carrying the operating system and application program running in real time. JVM memory layout defines the strategy of memory application, allocation and management in the running process of Java to ensure efficient and stable running of JVM. Different JVMS have some differences in the way of memory partition and management mechanism combined with JVM virtual machine specifications to discuss the classical JVM memory layout
- JVM runtime data area
- Thread-exclusive: Each thread has its own space, which is created and destroyed over the lifetime of the thread
- Thread sharing: All threads have access to this piece of memory data, which is created and destroyed with the VIRTUAL machine or GC
1 Program Counter Register
The name of Register comes from the CPU Register. The CPU can only run the Register and store the field information related to the instruction only after loading the data into the Register. Due to the LIMITATION of the CPU time wheel, during the concurrent execution of many threads, at any given moment, a processor or one of the cores of a multi-core processor, Only one instruction in a thread is executed. This will inevitably lead to frequent interruptions or recovery, how to ensure that there is no difference? After each thread is created, it will generate its own program counter and stack frame. Program counter is used to store the offset and line number indicator of the execution instruction. The thread execution or recovery depends on the program counter. Program counters do not affect each other between threads, and no out-of-memory exceptions occur in this area.
Definition 1.1.
A program counter is a small memory space that can be used as a line number indicator of the bytecode being executed by the current thread if the current thread is executing
- Java method
The counter records the address of the bytecode instruction being executed by the current thread
- Local method
The program counter value is undefined
1.2. Effect of
The program counter serves two purposes
- 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.
Characteristics of 1.3.
A small chunk of memory space is thread private. Each thread has a separate program counter. Is the only memory area that will not appear in the OOM. Life cycles are created with the creation of a thread and die with the end of the thread.
Java Virtual Machine Stack (JVM Stack)
Definition 2.1.
The JVM is a stack-based environment as opposed to a register-based environment. The stack structure is more portable and controllable.
The virtual machine stack in the JVM is the area of memory that describes the execution of Java methods and is thread private.
The elements in the stack are used to support the virtual machine to make method calls. The process from the beginning of each method call to the completion of execution is the process from the stack frame to the stack frame.
2.2 structure
Stack frames are the basic structure in which methods are run.
- In an active thread, only frames at the top of the stack are valid, called
The current stack frame
- The method being executed is called
The current method
When the execution engine is running, all instructions can only operate on the current stack frame,StackOverflowError
Represents a stack overflow of requests, resulting in memory exhaustion, usually in recursive methods. The JVM can sweep the board, the virtual machine stack is its bellwether, and the stack frames of the current method are battlefields where the operation stacks are the soldiers involved in the battle
Virtual machine stack by pressing/out of the stack, each method corresponding to the active stack frame operation processing, the normal execution of the method, will definitely jump to another stack frame. In the process of execution, if there is an exception, it will backtrace the exception, and the return address is determined by the exception handling table.
Stack frames play a very important role in the entire JVM system, including: local variable table, operation stack, dynamic link, method return address, etc.
Local variable scale
Store method parameters and local variables. Local variables have no preparation phase and must be explicitly initialized, as opposed to the preparation and initialization phases of class attribute variables. If the method is non-static, the instance reference of the object to which the method belongs is stored at the index[0] position, followed by parameters and local variables. The STORE instruction in the bytecode instruction is to write the local variable calculated in the operation stack back into the storage space of the local variable table.
The operand stack
A bucket stack whose initial state is empty. Since Java has no registers, all arguments are passed using the operand stack. During method execution, various instructions write and extract information onto the stack. The EXECUTION engine of the JVM is a stack-based execution engine, where the stack refers to the operation stack. The bytecode instruction set is defined based on the stack type, and the depth of the stack is in the stack property of the method meta-information.
The operation stack interacts with the local variable table
- The detailed order of bytecode operations is as follows:
The first part explains: the local variable table is like a medicine cabinet with many drawers numbered 0, 1, 2,3,.,.n bytecode instructionsistore_ 1
The stack is a deep vertical bucket. Only the barrel elements can be operated at any time, so the data can only be accessed at the top of the stack
Some commands can be done directly in the drawer, likeinc
The difference between I ++ and ++ I, common during programmer interviews, can be compared in bytecode
iload_ 1
Take a number from the first drawer of the local variable table and push it to the top of the stack. The next step is to implement the +1 operation directly in the drawer, which has no effect on the value of the top element of the stack
So ISTore_ 2 just assigns the top element to A
- In the right column of the table, the +1 operation is performed in drawer 1, and then iload_ 1 pushes the number in drawer 1 to the top of the stack, so istore_ 2 stores the value after +1
I++ is not an atomic operation. Even with the volatile keyword, multiple threads writing at the same time can cause data overwrite each other.
Dynamic connection
Each stack frame contains a reference to the current method in the constant pool to support dynamic concatenation during method calls.
Method return address
There are two exits when a method executes:
- The normal exit
RETURN bytecode instructions normally executed to any method, such as RETURN, IRETURN, ARETURN, etc.
- Abnormal exit
Either way, it returns to where the method was currently called. Method exit is equivalent to popping up the current stack frame.
There are three possible ways to exit:
- The return value is pressed into the upper call stack frame
- The exception message is thrown to a stack frame that can handle it
- The PC counter points to the next instruction after the method call
The Java virtual machine stack is an in-memory model that describes how Java methods run. The Java virtual machine stack creates “stack frames” for each Java method to be run. Used to store some information that the method needs to run.
- Local variable scale
Holds variables of basic data type, variables of reference type, and variables of type returnAddress
- The operand stack
- Dynamic link
- Constant pool pointer to the current method
- The return address of the current method
- Method export and other information
Each method, from being called to being executed, corresponds to the process of a stack frame in and out of the JVM stack
Note: It is often said that Java’s memory space is divided into “stacks” and “heaps,” with local variables in the stack and objects in the heap. That’s not entirely true! The “heap” here can be understood that way, but the “stack” here is the virtual machine stack, or the local variable table part of the Java virtual machine stack. The real 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 characteristics of
The local variable table is created as the stack frame is created when the method is executed. The size of the table is determined at compile time, and only a predetermined size is allocated at creation time. The size of the table does not change as the method runs. There are two exceptions to the Java virtual machine stack:
- StackOverFlowError
If the memory size of the Java virtual machine stack does not allow dynamic scaling, this exception is raised when the stack depth requested by the thread is greater than the maximum allowed by the virtual machine (but there may be more). The default maximum stack size is 1 MB, and a StackOverflowError is raised when the stack depth exceeds the maximum allowed by the virtual machine
- OutOfMemoryError
OutOfMemoryError is raised if the memory size of the Java virtual machine stack allows dynamic expansion, and the memory is exhausted when the thread requests the stack and cannot be dynamically expanded
The Java virtual machine stack is also thread-private, with each thread having its own Java virtual machine stack that is created as the thread is created and dies as the thread dies.
3. Native Method Stack
Similar to the function of the virtual machine stack, the virtual machine stack is prepared for the virtual machine to execute JAVA methods. The virtual machine specification does not specify specific implementation, but is implemented by different VIRTUAL machine vendors. The virtual machine stack and the local method stack are implemented the same way in the HotSpot VIRTUAL machine. Also, a StackOverflowError is thrown when the size is exceeded.
The Native method stack and the Java virtual machine stack perform almost the same functions as throwing exceptions except that the virtual machine stack serves Java methods (that is, bytecode) executed by the virtual machine, and the local method area serves Native methods used by the virtual machine.
In the JVM memory layout, thread objects are private, but the vm stack is “inside”, while the local method stack is “outside”, which is specific to the JVM. The local method stack serves Native methods. You can enter a world that is no longer constrained by the JVM where Native methods can access the data area of the virtual machine at run time through JNI, You can even call registers, have the same power and permissions as the JVM and when you have a lot of native methods, it’s bound to weaken the JVM’s control over the system because it’s black box error messages. In the case of running OutOfMemory, the native heap OutOfMemory is still thrown by the native method stack
The best known native method is System.CurrentTimemillis (). JNI makes Java deeply use OS features and reuse non-Java code, but during the course of a project, if JNI is implemented in a large number of other languages, it loses cross-platform features. If you need to interact with native code, you can use an intermediate standard framework to decouple it, so that even if the native method crashes, the STABILITY of the JVM will not be affected. Of course, if you require very high execution efficiency, low-level cross-process operations, etc., you can consider designing JNI calls
4 Java Heap
Created when the JVM starts to hold instances of objects. The garbage collector mainly manages heap memory. The birthplace of the Heap is the most main OOM fault, it stores the almost all of the instance objects, Heap by the garbage collector automatic recovery, Heap area used by the child thread sharing Normally, it takes the space is the largest of all memory area, but if the unrestrained to create a large number of objects, it is easy to run out of all the space of the heap memory space can be either fixed size, It can also be adjusted dynamically at run time by setting initial and maximum values with parameters such as
-Xms256M. -Xmx1024M
Copy the code
Where -x indicates that it is a JVM run parameter
- Ms is short for MemoryStart Minimum Heap Capacity
- Mx is short for Memory Max maximum heap capacity
However, in most cases, the heap space is constantly expanding and shrinking while the server is running, which inevitably causes unnecessary system stress. Therefore, in online production environments, THE Xms and Xmx of the JVM are set to be the same size to avoid extra stress when the heap size is adjusted after GC
The heap is divided into two large blocks: Cenozoic and old age objects are created in the beginning of the Cenozoic and enter the old age as they mature, but the old age also accepts oversized objects that cannot be accommodated in the new age
Generation = 1 Eden zone + 2 Survivor zone Most objects are generated in Eden zone. When Eden zone is filled, Young GC will be triggered. During garbage collection, the clearing policy is implemented in Eden area, and objects that are not referenced are directly collected. The objects that are still alive will be moved to the Survivor zone, which is really a Survivor zone. S0 and S1 are the two Survivor Spaces. Which space are they moved to? At each Young GC, the surviving objects are copied to the unused space, and then the currently used space is cleared completely. The usage status of the two Spaces is changed. If the objects that YGC wants to move are larger than the Survivor space limit, If some unambitious subjects think they can keep swapping in the Survivor zone of the new generation, they’re wrong. Each object has a counter, and YGC increments by 1 each time.
-XX:MaxTenuringThreshold
Copy the code
Parameter can be configured when the value of the counter reaches a certain threshold, the object is promoted from the new generation to the old generation. If this parameter is set to 1, the Eden area of the Cenozoic era is moved to the old era. The default value is 15 and can be promoted to the old age after 14 swaps in Survivor zones
If the Survivor zone cannot be laid down, or the threshold of the super-large object exceeds the upper limit, allocation is attempted in the old age. Full Garbage Collection(Full GC) is triggered if the old years cannot be laid down; If you still can’t put it down, throw OOM.
The heap has the highest OOM probability of running out of memory exceptions of all. The heap information is very helpful to solve the problem, so set the JVM to run parameters –
XX:+HeapDumpOnOutOfMemoryError
Copy the code
Enable the JVM to output heap information when encountering an OOM exception
Heap memory is divided differently in different JVM implementations and different reclamation mechanisms
Store all class instances and array objects in addition to instance data, but also save other information of the object, such as Mark Word (store object hash code, GC flag, GC age, synchronization lock and other information), Klass Pointy(Pointers to storage type metadata) and some byte-aligned padding (no padding if instance data is exactly 8-byte aligned)
The characteristics of
The largest chunk of memory that the Java virtual machine needs to manage.
Heap memory does not have to be physically contiguous, just logically contiguous, just like disk space. The heap is the main area of garbage collection, so it is also referred to as the GC heap.
The size of the heap can be fixed or expanded, but the mainstream virtual machine heap is scalable (controlled by -xmx and -xMS), so OutOfMemoryError is thrown when the thread requests memory allocation but the heap is full and cannot be expanded.
Thread sharing The entire Java virtual machine has only one heap, and all threads access the same heap. It is an area of memory that is shared by all threads and is created when the virtual machine starts. The program counter, Java virtual machine stack, and local method stack are all one thread at a time
Five methods area
5.1 define
The Java Virtual Machine specification defines the method area as a logical partition part of the heap. The specific implementation depends on different virtual machines. For example: HotSpot puts the method area in the persistent generation in Java7, Java8 in the metadata space, and manages the area through GC alias non-heap to distinguish it from the Java Heap. The method area holds information about classes that have been loaded by the virtual machine, constants, static variables, JIT compiled code, and other data.
5.2 the characteristics of
- Threads share
The method area is a logical part of the heap and, like the heap, is shared by threads. There is only one method area in the entire virtual machine.
- The permanent generation
The information in the method area generally needs to exist for a long time, and it is the logical partition of the heap, so with the partition method of the heap, we call the method area permanent generation.
- The memory reclamation efficiency is low
The Java Virtual Machine specification is lax about method areas, and garbage collection can be omitted. The information in the method area is usually persistent, and only a small amount of information may be invalid after the memory is reclaimed. The primary goal of memory reclamation for the method area is to reclaim the constant pool and unload the type
Like the heap, fixed size is allowed, scalable size is allowed, and garbage collection is not allowed.
OutOfMemoryError is thrown when the method area memory space cannot meet the memory allocation requirements.
5.3 Runtime Constant Pool
5.3.1 definition
The runtime constant pool is part of the method area. The method area holds three types of data: class information, constants, static variables, and just-in-time compiler compiled code. Constants are stored in the runtime constant pool.
As we know, the.class file generated after the.java file is compiled contains: In addition to the version, field, method, and interface information of a class, the constant pool contains various literals and symbolic references generated at compile time. All the contents of the constant pool in the.class file are stored in the runtime constant pool of the method area after the class is loaded.
//age is a variable that can be assigned; 21 is a literal constant and cannot be assigned;PS:int age = 21;
//pai is a symbolic constant that cannot be modified once assigned.
int final pai = 3.14;
Copy the code
The Constant Pool table is used to store various literals and symbolic references generated at compile time. This part of the table will be stored in the runtime Constant pool after the Class is loaded. Another feature of the runtime constant pool over the Class file constant pool is that it is dynamic. The Java language does not require that constants must be generated only by the compiler. That is, constants that are not preset into the class file constant pool can be entered into the method area runtime constant pool, and new constants may be added to the pool at runtime.
In the last three JDK versions (6, 7, 8), the area of the runtime constant pool has been constantly changing. In JDK6, it was part of the method area. In fact, this also shows that the official optimization of “permanent generation” has been started since 7
5.3.2 features
The constant pool in the class file is dynamic. Instead of requiring constants to be generated only at compile time,Java allows new constants to be put into the run-time constant pool of the method area at run time. The intern() method in the String class takes advantage of the runtime constant pool dynamics. When the intern method is called, if the pool already contains a String equal to this String object, the String from the pool is returned. Otherwise, the String is added to the pool and a reference to the String is returned.
5.3.3 Possible Exceptions
The runtime constant pool is part of the method area and is therefore limited by method area memory, so OutOfMemoryError is thrown when the constant pool can no longer claim memory.
We usually declare a constant ina class through public static final. This Class is compiled to generate a Class file in which all information about the Class is stored.
When the class is loaded by the Java Virtual machine, the constants in the class file are stored in the runtime constant pool in the methods area. And at run time, new constants can be added to the constant pool. For example, the Intern () method of the String class adds String constants to the constant pool at run time.
When some constants in the run-time constant pool are not referenced by objects and are not referenced by variables, then the garbage collector needs to collect them.
6 Direct Memory
Direct memory is not part of the run-time data area of the VIRTUAL machine, nor is it an area of memory defined in the JVM specification, but it is frequently used during the actual running of the JVM. And I’m also going to flip OOM
NIO(New) was added in JDK 1.4 The Input/Output class introduces a pipe-based and buffer-based IO approach, which can use Native libraries to allocate out-of-heap memory directly, and then manipulate data in out-of-heap memory through a DirectByteBuffer object stored in the heap as a reference to that memory. This can significantly improve performance in some scenarios because it avoids copying data back and forth between the Java heap and Native heap.
All this seems to be
The program counter, Java virtual machine stack, and local method stack are thread private, that is, each thread has its own program counter, Java virtual machine stack, and local method area. And their life cycle is the same as the thread they belong to. While the heap and method area are shared by threads, there is only one heap and one method stack in the Java VIRTUAL machine. It is created when the JVM starts and destroyed when the JVM stops.
7 Metaspace
In JDK8, the precursor of the meta space, Perm area, has been phased out. In JDK7 and previous versions, only Hotspot has Perm area (permanent generation), which is fixed in size at startup, difficult to tune, and moves the class meta information when Full GC.
In some scenarios, if too many classes are dynamically loaded, OOM in the Perm area may be generated. For example, in a practical Web project, due to a large number of function points, many classes need to be dynamically loaded during operation, and fatal errors often occur:
Exception inThread 'Dubbo client X.x connector' java.lang.OutOfMemoryError: PermGenspac
Copy the code
To solve this problem, you need to set the running parameters
-XX:MaxPermSize= l280m
Copy the code
If you deploy to a new machine, the failure will often recur because JVM parameters have not been modified. In addition to the fact that people unfamiliar with the application often struggle to troubleshoot problems, the persistent generation has a number of problems with GC
So, JDK8 uses meta-space to replace permanent generations. Unlike permanent generation, meta-space is allocated in local memory. That is to say, as long as local memory enough, it won’t appear like permanent generation in Java. Lang. OutOfMemoryError: PermGen space
In JDK8 or later, when MaxPermSize is set, the JVM does not raise an error message at startup.
Java HotSpot 64Bit Server VM warning:ignoring option MaxPermSize=2560m; support was removed in 8.0
Copy the code
By default, the size of the “metaspacesize” can be adjusted dynamically, or the new parameter MaxMetaspaceSize can be used to limit how much local memory can be allocated to class metadata.
In JDK8, all content in the Perm section
- String constants are moved to heap memory
- Other content, including class meta-information, fields, static properties, methods, constants, and so on, is moved into the meta-space
For example, Object meta information, static property System.out, integer constant 000000, etc. are displayed in the constant pool in the figure, whose actual objects are stored in the heap memory.
Meta-spatial characteristics
- Take full advantage of the Java language specification: the life cycle of classes and associated metadata is consistent with that of the class loader
- Each class loader has its own area of memory – the meta-space
- It’s just a linear assignment
- Never reclaim a single class (except for RedefineClasses or class loading failures)
- No GC scanning or compression
- Objects in the meta space are not transferred
- If the GC finds that a class loader is no longer alive, the entire meta-space is collectively reclaimed
GC
- During Full GC, Pointers to metadata are no longer scanned, reducing Full GC time
- Much of the complex metadata scanning code (especially in the CMS) has been removed
- The meta-space has only a few Pointers to the Java heap
This includes: Pointers to instances of java.lang.Class in the metadata of the Class; Pointer to the java.lang.Class collection in the metadata of the array Class.
- There is no metadata compression overhead
- Reduced GC Root scanning (no longer scanning directories of loaded classes and other internal hash tables in the virtual machine)
- In the G1 collector, classes can be unloaded once the concurrent marking phase is complete
Meta – space memory allocation model
- Most of the space for class metadata is allocated in local memory
- Objects used to describe class metadata are also removed
- Multiple mapped virtual memory Spaces are allocated for metadata
- Each class loader is assigned a list of memory blocks
- The size of the block depends on the type of class loader
- Java reflection of the bytecode accessors (sun.reflect.delegatingclassloaders) smaller footprint
- Free block memory is returned to the block memory list
- When the meta-space is empty, the virtual memory space is reclaimed
- Reduced memory fragmentation
Finally, from the perspective of thread sharing
- The heap and meta-space are shared by all threads
- The virtual machine stack, local method stack, and program counter are private within the thread
Take a look at the Java memory structure from this perspective
Look at the Java heap from a GC perspective
The heap and method areas are shared by threads and are used to store information about objects. We know that multiple implementation classes in an interface may require different amounts of memory, and branches in a method may require different amounts of memory. We don’t know what objects will be created until the program is running, so memory and collection are dynamic. This is the part of memory that the garbage collector is concerned with (and only this part of memory is referred to as “memory” allocation and reclamation later in this section). This memory allocation is also different in JDK1.7 and 1.8, so let’s look at it in detail
The heap memory allocation in Java8 looks like this:
9 the JVM closed
- Normal shutdown: When the last non-daemon thread terminates or calls System.exit or in some other platform-specific way, such as CTRL + C.
- Force shutdown: Call the Runtime.halt method, or kill the JVM process in the operating system.
- Exception Shutdown: RuntimeException is encountered during running
In some cases, we need to do some cleaning when the JVM is shut down, such as deleting temporary files and stopping the logging service. For this, the JVM provides shutdown hocks to do these events.
The Runtime class encapsulates the Runtime environment of a Java application. Each Java application has an instance of the Runtime class, and users can connect to the Runtime environment.
A closing hook is essentially a Thread (also known as a HOCK Thread) that registers a closing hook with the main JVM via the Runtime addShutdownhock (Thread Hock). The Hock thread executes when the JVM is normally shut down, forcing the shutdown not to execute.
For multiple closed hooks registered in the JVM, they execute concurrently, and the JVM does not guarantee their execution order.
reference
- Code Efficient