There is a "high wall" between Java and C + + that is surrounded by dynamic memory allocations and garbage collection techniques, and people outside the walls want to go in, but the people inside the wall want to come out. --in-depth understanding of Java Virtual machines: JVM advanced features and best practices
The Java Virtual machine divides the memory it manages into several different data regions during the execution of a Java program. These areas are used for their own purposes. And the time of creation and destruction. Some regions exist as virtual machine processes start, and some regions rely on user thread initiation and termination to build and destroy.
Program counter
The program counter only occupies a small piece of memory space.
Can be thought of as the line number indicator of the bytecode file (class) executed by the current thread. In the virtual machine world, the byte code parser is to choose the next execution of the bytecode instruction by changing the value of the counter, branching, looping, jumping, exception handling, thread recovery, etc., all need to pass the program counter to achieve.
Because the processor only executes the instructions in one thread at a certain time, after the thread switches, the execution traces are recorded by the counter, so it can be seen that the program counters are private to each thread.
If you are executing a Java method, the address of the address of the executing virtual machine bytecode instruction is logged, and if it is the native method, the value of the counter is empty (undefined)
This memory area is the only case where the Java Virtual Machine specification does not stipulate the task OutOfMemoryError
Java Virtual Machine stack
Like the program counter, the Java Virtual machine stack is also thread-private, with the same life cycle as the thread. The virtual machine stack describes the memory models that are executed by the Java method, each of which creates a stack frame to store information such as local variable tables, operand stacks, dynamic links, method exits, and so on. Each method from the invocation until the completion of the process, corresponding to a stack frame in the virtual machine stack from the stack to the process of the stack.
Local variable table
A local variable table is a storage space for a set of variable values that holds method parameters and local variables. The variable slot (Variable slot) is the smallest unit of a local variable table, with no mandatory size of 32 bits, although 32 bits are sufficient to hold most types of data. A slot can be a method of Boolean, Byte, char, short, int, float, reference, and ReturnAddress 8 types.
Where reference represents a reference to an object instance, through which you can get the index of the starting address that the object holds in the Java heap and the type information for the method area of the data type to which the data belongs. The returnaddress points to the address of a bytecode instruction. For a 64-bit long and double variable, the virtual opportunity allocates two contiguous slot spaces for it.
The virtual machine uses the local variable table in the way that the index locates. In order to save stack frame space, the slot in the local variable table is important. When you leave the scope of certain variables, the slots corresponding to those variables can be used by other variables.
Operand stacks
The operand stack, also known as the Operation Stack, is a post-in-first-out stack. The arithmetic operation in the execution of the method, or the invocation of other methods for parameter passing, is carried out by the operand stack. In the conceptual model, two stack frames are independent of each other. However, the implementation of most virtual machines is optimized to make a portion of the two stack frames overlap. Make the following part of the operand stack overlap with the local variable table above, so that a portion of the data can be shared at the time of the method call, without additional parameter copy passing
Dynamic links
Each stack frame contains a reference to the method that the stack frame belongs to in the run-time pool, which is held to support dynamic linking during method invocation
Method return Address
When a method starts executing, there are only two ways to exit the current method:
When execution encounters a return instruction, the return value is passed to the upper-level method caller, which is called the normal completion exit, in general, the caller's PC counter can be used as the return address
When execution encounters one time, and the current method body is not processed, it causes the method to exit, there is no return value, called the exception completion exit, the return address to be determined by the Exception processor table
When a method returns, there are 3 possible actions:
Restore local variable tables and operand stacks for upper-level methods
Pushes the return value into the operand stack of the caller's call stack frame
Adjust the value of the PC counter to point to an instruction that follows the method invocation instruction
Local method Stack
The role of the local method stack and the virtual machine stack is very similar, but the difference between them is that the virtual machine stack executes Java methods (that is, bytecode) services for the virtual machine, while the local method stack is the native method service used by the virtual machine.
In the virtual machine specification, the language used for methods in the local method stack, usage and data structures are not mandatory, so the specific virtual machine can be implemented freely. Even some virtual machines, such as Sun hotsport virtual machines, directly combine the local method stack with the virtual machine stack, and the local method stack area throws Stackoverflowerror and OutOfMemoryError exceptions.
Java heap
For most applications, the Java heap is the largest piece of memory managed by a Java virtual machine. The Java heap is a piece of memory that is shared by all threads and created when the virtual machine is started. The only purpose of this area of memory is to hold object instances where almost all of the object instances are allocated memory.
The Java heap is the primary area of the garbage collection manager. So it is often called a "GC" heap. From the memory recovery point of view, because the collector now basically uses the Generational collection algorithm. So the Java heap can also be subdivided into: the new generation and the old age: a little more detailed there is Eden space, from Survivor space, Tosurvivor space and so on.
From the memory allocation point of view, the thread-shared Java heap may divide the allocation buffers that are private to multiple threads. However, regardless of how the partition, is not related to the content, no matter what area, storage is still an object instance, the purpose of further division is to better reclaim memory, or to allocate memory more quickly.
The Java heap can handle physically discontinuous memory space, as long as it is logically contiguous. A Outofmenoryerror exception will be thrown if there is no memory in the heap to complete the instance assignment and the heap can no longer be expanded.
Method area
The method area, like the Java heap, is an area of memory shared by each thread that stores data such as class information, constants, static variables, and code compiled by the immediate compiler that have been loaded by the virtual machine.
The method area is also called the permanent generation, in the past (when the custom ClassLoader is not quite common), the classes are mostly "static", are rarely unloaded or collected, and are therefore referred to as "permanent (Permanent)".
Although the Java Virtual Machine specification describes the method area as a logical part of the heap, it has an alias called Non-heap (Not a heap), which should be distinguished from the Java heap. Also, because class classes are part of the JVM implementation and are not created by the application, they are considered "non-heap (non-heap)" Memory.
Run a constant-rate pool
The run-time pool is part of the method area, and in addition to the description of classes in the class file, such as the version, field, method, interface, and so on, there is a constant pool that holds the various constants and conforming references generated during the compilation period, and this is stored in the run constant pool of the class load backward into the method area.
Direct Memory
Direct memory is not part of the data area when the virtual machine is running, nor is it an area of memory defined in the Java VM specification. In JDK1.4, a new Input/output class was added and a channel-based approach was introduced. (Channel) with buffer I/O, he can use the native library to directly allocate out-of-heap memory and then manipulate it through a Directbytebuffer object stored in the Java heap as a reference to that memory.
This can significantly improve performance in some scenarios, thus avoiding copying data back and forth in the Java heap and the native heap.
What happened to the new object?
Object creation
Java is an object-oriented programming language, the Java program in the process of running the object is created all the while, at the language level just use the New keyword, and in the virtual machine, the creation of the object is what a process?
1. Class Load Check
Virtual opportunity to a new directive, first checks whether the parameter of the directive can be positioned in a constant pool to conform to a class's reference, and checks if the class that conforms to the reference has been loaded, parsed, and initialized. If not, you must first perform the appropriate class loading process.
2. Object Allocation memory
After the class load check passes, the virtual machine then allocates memory for the new object. The size of the memory required by an object is fully determined after the class is loaded, and the task of allocating space to an object is equivalent to dividing a size of memory from the Java heap. Depending on whether the memory in the Java heap is structured, there are 2 ways to handle it:
1, pointer collision (Bump the pointer)
The memory in the Java heap is regular, all the used memory is on one side, the free memory is on the other side, a pointer is placed in the middle of the point indicator, allocating memory is to move the pointer to the free space beyond the distance of the size of the memory. For example: Serial, parnew and other collectors.
2, free list
The memory in the Java heap is not regular, the memory used and the free memory interleaved, there is no way to simply do a pointer collision. The virtual machine must maintain a list of which memory blocks are available, find a large enough space in the list to be allocated to the object instance, and update the records on the list. For example, CMS is a collector based on the mark-sweep algorithm. Concurrent Processing:
Object creation is a very frequent behavior in a virtual machine, and even if you just modify the location pointed to by a pointer, it is not thread-safe in concurrency, it is possible to allocate memory for object A, the pointer has not yet been modified, and object B uses the original pointer to allocate memory. There are 2 types of treatment options:
1, synchronous processing
Synchronous processing of the action of allocating memory space, in fact, the virtual machine uses the CAS with the failure retry to ensure the atomicity of the update operation.
2,tlab
The memory allocation action is divided into different spaces by thread, that is, each thread allocates a small chunk of memory in the Java heap, called the local thread allocation buffer (thread local Allocation buffer,tlab). That thread allocates memory, it is allocated on the tlab of which thread, and only when Tlab runs out and assigns a new Tlab, does it need to be locked synchronously.
3. Initialization of memory space
The memory space that the virtual machine allocates to is initialized to a value of 0 (excluding the object header), and if Tlab is used, the work process can be done in advance to Tlab allocation.
Memory space initialization guarantees that an instance field of an object can be used directly in Java code without assigning an initial value, and the program can access the 0 value corresponding to the data type of those fields.
4. Object Settings
Next, the virtual machines make the necessary settings for the object, such as the object is an instance of that class, how to find the metadata information of the class, the object's hash code, the object's GC generational age, and so on. This information is stored in the object header of the object.
5. Execute init ()
After the above work is done, a new object has been created from the virtual machine's point of view. But from the Java program's point of view, the creation of the object has just begun the Init () method has not been executed, all fields are still zero.
So, in general (as determined by the Invokespecial directive in bytecode), the init () method is followed by the execution of the new instruction, which initializes the object according to the programmer's will, so that a truly usable object is generated.
Object Memory Layout
The memory structure of an object can also be divided into: object header, instance data, object padding.
Object Header
The object header consists of two pieces of information:
1, used to store the object's own run-time data, such as hash code (HASHCODE), GC generational age, lock status flag, thread-held lock, biased thread ID, biased time stamp, and so on, this part of the data length of 32-bit and 64-bit virtual machine (temporarily The scenes that do not consider opening the compression pointer are 32 and 64 bits, respectively, which the official calls "Mark Word".
Store Content flags state object hash code, object generational age 01 unlocked pointer to lock record 00 Lightweight lock pointer to heavyweight lock 10 expansion (Heavyweight lock) NULL, no need to record information 11GC tag biased to thread ID, biased timestamp, object generational age 01 can be biased.
2, the type pointer, which is the pointer to the metadata of the class that the object points to, the virtual machine uses this pointer to determine which class instance the object is.
Instance data
Valid information that the object actually stores, as well as the various types of field content defined in the program code. Whether it is inherited from a parent class or defined by a subclass, it needs to be documented.
Object fills
It doesn't really make sense, it just plays the role of placeholder. The size of the object must be an integer multiple of 8 bytes.
Object Access Targeting
The object is created to use the object, and our Java program needs to manipulate the concrete objects on the heap through the reference data on the stack. Since the Java Virtual Machine specification only specifies that the reference type is a reference to an object, and does not define how the reference should be used to locate, access to the object in the heap, the object's access depends on the virtual machine implementation.
There are two ways to access the mainstream: using a handle and a direct pointer.
Handle Access
If accessed using a handle, a chunk of memory is partitioned into the Java heap as the handle pool, where the handle of the object is stored, and the handle contains the specific address information of the object instance data and the type data in the reference.
Pointer Access Object
With direct pointer access, the layout of the Java heap object must consider how to place information about the access type data that is stored directly in the Reference object address.
There are advantages to both object access, and the greatest benefit of using a handle to access is that the stable handle address is stored in reference, and only the instance data pointers in the handle are changed when the object is moved (garbage collection is a very common behavior), and the reference itself does not need to be modified.
The greatest benefit of using a direct pointer to access is faster, which saves time spent on pointer positioning, because object access is very frequent in Java, so this kind of overhead is much smaller than a very significant implementation cost. As you can see from the memory layout of the objects explained in the previous section, it is the second way to access the object in terms of the virtual machine hotspot, but it is common to see the use of handles in various languages and frameworks throughout the software development context.
JVM Memory management mechanism