An overview of the
- Program counter
Data area distribution during running of THE JVM
Program Counter Register
Program counters, also known as PC registers, are memory Spaces that are private to the thread.
Program counter functions:
- Provides a line number indication for bytecode executed by the current thread
- Bytecode interpretation execution selects the next bytecode instruction to execute by changing the value stored in this counter
- Branches, loops, jumps, exception handling, and thread recovery all depend on this register
The program registers are equivalent to each thread’s private memory space. Each thread registers do not affect each other and are stored independently.
Workflow:
- If the thread is executing a Java method, the PC Register records the address of the JVM bytecode instructions being executed
- This counter is null (Undefined) if the thread executes a Native method.
The MEMORY area of the PC Register is the only one that does not cause OutOfMemoryError cases
Java Virtual Machine Stacks
This area is thread private; And the life cycle is the same as the thread; It describes the in-memory model of Java method execution; Each Java method runs with a Stack Frame; Stack frame stores local variable table, operand stack, dynamic link, method return and other information;
Contents: Local variables to store the compile time shows the various basic data types (Boolean/byte/char/short/int/float/log/double), object reference (reference), returnAddress pointer (pointing to a bytecode instruction address)
Space storage and expansion: 64-bit long and double data occupy two local variable Spaces (slots); The remaining data types occupy one, and the amount of space that local variables occupy is determined by the compiler and does not change during the execution of the method
Related exceptions: The JVM virtual machine specification specifies two exceptions related to this area:
- StackOverflowError is thrown if the stack depth of the thread request is greater than a certain range
- If the virtual stack can expand memory dynamically, OutOfMemoryError will be raised when sufficient memory cannot be allocated
Native Method Stack
The working principle and mechanism is the same as that of the Java virtual machine stack, except that the Native method stack operates on the Native method used by the JVM and also throws the above two exceptions. In JDK1.7, HotSpot combines the two method stacks into one.
The Java Heap (Java Heap)
The Java heap is the largest chunk of memory managed by the JVM; The Java heap is thread shared and is created when the virtual machine is started
Storage content: This memory area is mainly used to store object instances. Almost all object instances and arrays are allocated memory here. This is not always the case; JIT compilers and escape analysis techniques allow objects to be allocated elsewhere on the stack
Space allocation and garbage collection: The Java heap is the primary area managed by the garbage collector
- Due to the generational recycling algorithm, the Java heap can be subdivided into new generation and old generation
- It is subdivided into Eden Space, From Survivor Space, To Survivor Space, etc
- From a memory allocation point of view, it can be divided into buffers that are private to multiple threads.
Space expansion and exceptions: Most current virtual machines are scalable for the heap (controlled by -xmx and -xMS) and throw OutOfMemoryError if there is no space to expand
Method Area
The method area is an area of memory shared by individual threads
Contents: The method area stores data such as class information, constants, static variables, and bytecodes compiled by the real-time compiler that have been loaded by the VIRTUAL machine. Alias: Non – Heap
Permanent Generation: For the Hotspot virtual machine, the method area is also called Permanent Generation because it is part of the garbage collection memory. You can set the size of the permanent generation by running -xx :MaxPermSize
Exception: OutOfMemoryError is thrown when the method area cannot meet memory allocation requirements
Runtime Constant Pool
Store content: The runtime constant pool is the part of the method area that holds the various literal and symbolic references generated at compile time. In addition to keeping the conforming references described in the Class file, the compiled direct references are also stored
Dynamic: Constants do not have to be generated only at the compiler. Not only the contents of the preset Class file constant pool can be entered into the method area runtime constant pool, but new constants may also be put into the pool at run time
Exception: A memory overflow exception is thrown when the constant pool can no longer allocate memory
Direct Memory
Direct memory is also called off-heap memory
NIO frameworks such as Netty will call a large number of Native function libraries to directly allocate out-of-heap memory, and then operate through a DirectByteBuffer object stored in the Java heap as a reference to this memory, which can significantly improve performance and avoid data replication between the Java heap and Native heap.
Out-of-heap memory is not limited by the JVM heap size, but by the total native memory size and processor addressing space
The appendix
- Out of memory: www.jianshu.com/p/35cf0f348…
The HotSpot virtual machine
We wanted to explore the process in the HotSpot VIRTUAL machine with the following objects:
- Object creation process
- Object memory distribution
- The process of accessing and locating objects
Object creation
Common object creation steps:
- New keyword instruction
- Class loading check: Checks whether there is a match reference in the constant pool and whether the class represented by the match reference has been loaded, parsed, and initialized. If not, the class loading process must be performed first
- Usually, after class loading passes, objects are created in the new generation first
- Allocating memory space
- If the memory in the Java heap is absolutely neat, Bump the Pointer to the used and unused memory on both sides, with a Pointer in the middle as an indicator of the dividing point, offsetting the memory size of an object
- If the memory in the Java heap is not tidy and is stored alternately with Free and used memory, the virtual machine maintains a Free List from which it applies for space
- Collectors of the Compact algorithm class, such as Serial and ParNew, allocate memory using pointer collisions
- Collectors of the Mark-sweep algorithm class, such as CMS, allocate memory using free lists
- Memory allocation: two solutions to atomicity
- Synchronize the memory allocation actions of multiple threads: The VM uses the FAILED retry mode after the CAS configuration to ensure atomicity of pointer update operations
- Each thread is pre-allocated a small block of memory in the Java heap: this memory is thread exclusive, calledTLAB(Thread Local Allcation Buffer), the CAS synchronization mechanism is used only after the TLAB Buffer space is used up
-XX:+/UseTLAB
Parameter specifies whether to use TLAB
- After memory allocation is complete, object initialization begins
- By default, the virtual machine initializes the memory space of the object to zero
- If TLAB is used, this operation is advanced until TLAB allocates memory
- The goal is not to assign an initial value to each instance field of an object
- Start setting the following properties of the Object Header
- An instance of which class the object belongs to
- Class metadata information
- Object Hash code of an object
- The GC generation age of the object
- Whether biased locking is enabled
- At this point, the new instruction completes, and then the init instruction is executed, which starts the rest of the initialization as the programmer wishes
Object memory layout
In the HotSpot VIRTUAL machine, objects are stored in memory in three areas
- Object head (Header)
- Instance Data
- Align Padding
The object header is divided into two parts:
- Mark Word: Stores runtime data for the object itself
- HashCode
- GC generational age
- Lock status flag
- The lock held by the thread
- Biased thread ID
- Bias timestamp
- Type pointer: A pointer to an object’s class metadata to determine which class the object is an instance of. The JVM does not necessarily preserve type Pointers.
- Array length: If the object is a Java array
Instance data: This is the valid information that the object actually stores, and the order in which the vm allocation policy parameters and fields are defined in the Java source code
Alignment padding: not necessarily there and acts as a placeholder because HotSpot requires all objects to be multiples of 8 bytes
Object access location
Objects are accessed by manipulating specific objects on the heap using reference data types on the stack.
The reference type is just a reference to an object defined in the JVM, but it does not define how to use this reference access to locate and access the location of a specific object in the heap.
There are now two access methods in the mainstream heap:
- Handle access
-
In this access mode, the heap area is divided into a handle pool, and reference stores the address of the handle, which contains Pointers to object instance data and type data
-
Benefits: When the object is moved, only the instance data pointer in the handle changes, and the address stored in reference remains the same
-
Direct pointer access
- A reference accessed by a direct pointer stores the direct address of the object
- Benefits: Faster and saves the overhead of a pointer location, which is how HotSpot does it.
Combat memory overflow and stack overflow “TODO”
The Java heap overflow
Cause of overflow: The Java heap is used to store object instances. As long as objects are constantly created and GC Roots have a reachable path to the objects to avoid garbage collection, overflow occurs when the number of objects exceeds the maximum heap memory capacity
Related parameters:
- -Xms Sets the initial heap size
- -Xmx Sets the maximum value of the heap
- – XX: + HeapDumpOnOutOfMemoryError let the virtual machine in the case of memory Dump
Test code:
- HeapOOM
Test results:
Screening program
- Memory Leak and Memory Overflow
- Memory overflow: Insufficient memory
- The PermGenspace method area overflows
- The Java Heap Space overflows
- Unable to create new native thread: The number of OS threads is limited
- Memory leak: Memory space used up and not reclaimed
- Memory overflow: Insufficient memory
- If there is a memory leak, look at GC Roots’ reference chain to locate the code
- If not, check the parameter Settings and whether there are large objects with long life cycles
The virtual machine stack and local method stack overflow
Overflow cause:
- Throw StackOverFlowError if the stack depth requested by the thread is greater than the maximum virtual machine depth
- Throw OutOfMemoryError if the VM cannot obtain sufficient memory space in the extension stack:
- -Xss Sets the maximum memory capacity of the stack
- Xoss sets local method memory size (HotSpot useless)
Recursively call the test code:
https://github.com/zlserver/jvm_code/blob/master/%E7%AC%AC2%E7%AB%A0/%E6%B8%85%E5%8D%952-4.txt
Copy the code
Running results:
Construct a lot of thread test code 2:
/** * VM Args: -xss2m * @author ZZM */ public JavaVMStackOOM {private voiddontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() { dontStop(); }}); thread.start(); } } public static void main(String[] args) throws Throwable { JavaVMStackOOM oom = new JavaVMStackOOM(); oom.stackLeakByThread(); }}Copy the code
Running Result 2:
Method area and runtime constant pool overflow
Related parameters:
- -xx :PermSize Initial size of method area permanent generation (1.8 invalid)
- -xx :MaxPerSize Maximum size of the method area (1.8 invalid)
String.intern(): This method is a Native method that returns the String object if the String constant pool already contains a constant equal to the String, otherwise the String is added to the constant pool.
String constant pool: In JDK 1.6, a “PermGen Space” memory overflow occurs. In JDK 1.7 and JDK 1.8, a heap overflow occurs, and PermSize and MaxPermGen are invalid in JDK 1.8. Thus, you can roughly verify that JDK 1.7 and 1.8 moved string constants from permanent generations to the heap, and that permanent generations no longer exist in JDK 1.8.
The string constant pool overflows
Test code:
https://github.com/zlserver/jvm_code/blob/master/%E7%AC%AC2%E7%AB%A0/%E6%B8%85%E5%8D%952-6.txt
Copy the code
Run result (1.8 invalid): 1.8:
Dynamic proxy Cglib overflows
Test code:
https://github.com/zlserver/jvm_code/blob/master/%E7%AC%AC2%E7%AB%A0/%E6%B8%85%E5%8D%952-9.txt
Copy the code
Analysis: Through dynamic proxy, the information of an Object is continuously loaded during class loading
Native direct memory overflow
Related configurations:
- -xx :MaxDirectMemorySize Specifies the out-of-heap memory size
Test code:
https://github.com/zlserver/jvm_code/blob/master/%E7%AC%AC2%E7%AB%A0/%E6%B8%85%E5%8D%952-9.txt
Copy the code
Test result :(I didn’t test it myself in JDK1.8)
OutOfMemoryError