1. Java memory area
During the execution of Java programs, the Java virtual machine will divide the memory it manages into several different data areas. These areas have their own uses and the time for creation and destruction. Some areas exist as the virtual machine process is started, while others rely on the startup and end of user threads to be established and destroyed. According to the provisions of the "Java Virtual Machine Specification (JavaSE7 Edition), the memory managed by the Java virtual machine will include the following runtime data areas.
1. Program counter (thread private)
The Program Counter Register is a small piece of memory space, which can be regarded as a line number indicator of the bytecode executed by the current thread. In the conceptual model of a virtual machine, when the bytecode interpreter works, it selects the next bytecode instruction to be executed by changing the value of this counter. Basic functions such as branching, looping, jumping, exception handling, thread recovery, etc. need to rely on this counter to complete.
Each thread has an independent program counter, and each thread does not affect each other and stores it independently.
If the thread is executing a java method, the counter records the address of the executed virtual machine bytecode instruction;
If the thread is executing a Native method, the counter value is undefined.
This memory area is the only area that does not specify any OutOfMemoryError (OOM) situation in the Java specification
Virtual machine stack (thread private)
The virtual machine stack (Java Virtual Machine Stacks) describes the memory model of Java method execution: each method will create a stack frame while executing, which is used to store information such as local variable tables, operand stacks, dynamic links, method exits, etc. The process from call to execution completion of each method corresponds to the process of entering and exiting a stack frame in the virtual machine stack.
In the virtual machine heap memory and stack memory, stack memory generally refers to the local variable table part here.
The local variable table stores various basic data types, object references (not the object itself, but may be a pointer to the object or a handle representing the object or other locations related to this object, involving the "object access positioning" below) and returnAddress types.
3. Local method stack (thread private)
The role of the local method stack (Native Method Stack) and the virtual machine stack plays very similarly. The difference is that the virtual machine stack serves Java methods (byte code), while the local method stack serves the Native method used by the virtual machine. The Java virtual machine specification does not have mandatory regulations on the language, methods, and data structures used by the local method stack. Therefore, virtual machines can implement it freely, and some virtual machines even combine the local method stack and the virtual machine stack into one.
Heap (thread sharing)
The Java Heap (Java Heap) is the largest piece of memory managed by a virtual machine. The only purpose is to store object instances. All object instances and arrays must be allocated memory on the heap.
The Java heap is the main area of garbage collector management. The Java heap can be in a physically discontinuous memory space, as long as it is logically continuous, similar to disk space. When implemented, it can be either fixed-size or scalable. Current mainstream virtual machines are implemented as scalable. If no memory is instantiated in the heap and the heap cannot be expanded, an OOM exception will be thrown.
5. Method area (thread sharing)
The method area is used to store class information, constants, static variables, code compiled by the instant compiler and other data that have been loaded by the virtual machine.
The virtual machine specification describes the method area as a logical part of the heap, but has an alias Non-Heap.
6. Runtime constant pool (thread sharing)
Runtime Constant Pool is part of the method area.
In addition to the description information of the class version, field, method, interface, etc., there is also a constant pool in the class file, which is used to store various literal and symbolic references generated during the compilation period. This part of the content is saved in the runtime constant pool in the method area after the class is loaded.
Java virtual machines have strict regulations on the format of each part of the Class file. Each byte must comply with the specifications for storing any data to be recognized, loaded and executed by the virtual machine. However, for running constant pools, the Java virtual machine specification does not require any details, and different virtual machines can be implemented according to their own needs. However, generally speaking, in addition to saving symbolic references described in Class files, the translated direct references will also be stored in the runtime constant pool.
Another important feature of the constant pool during runtime is that it is dynamic. The Java language does not require constants to be generated only during compilation. New constants may also be placed into the pool during runtime. The most used one is the intern() method of the String class.
If you can no longer apply for memory, the OOM exception will be excluded.
2. HotSpot virtual machine object exploration
Discussion on the object allocation, layout and access process of HotSpot virtual machine in the Java heap.
1. Object creation
Java is an object-oriented language. Objects may be created at any time during the execution of a program. From a language level, creating objects (such as cloning, deserialization) is usually just the new keyword.
process:
Loading class:When a virtual machine encounters a new instruction, first check whether the parameters of this instruction can locate a symbolic reference of a class in the constant pool, and check whether the class represented by this symbolic reference has been loaded, parsed and initialized. If not, the corresponding class loading process will be performed. (The specific content of this part is not discussed here, please refer to Chapter 7 for details)
Allocate memory:After the class is loaded, the virtual machine must allocate memory for the new object. The memory required by the object can be determined after the class is loaded. Allocating space for the object is divided from the Java heap. There are two common methods at this time: (1) Pointer Collision: If the memory in the heap is absolutely regular, the ones that have been used are on one side, and the ones that have not been used are on the other side, and there is a split pointer in the middle, you only need to move the split pointer to the unused memory as a fixed size (2) Free list: The Java heap memory is not regular, and the unused ones that have been used are interleaved. The virtual machine needs to maintain a list to save which lists are used and which are not used. When allocating, you only need to allocate a fixed size to the new object from the unused memory.
Which method to choose is determined by whether the heap memory is regular, and whether it is regular depends on whether the garbage collector used has compression and sorting function.
It can be clearly seen that this method of allocating space is not thread-safe. It may be that before the pointer has been modified when allocating object A, object B uses the original pointer. There are two solutions to solve this problem:
(1)Synchronize the actions of allocating space: In fact, the virtual machine uses CAS and failed retry to maintain the atomicity of the update operation (either done everything or not at all).
(2)The memory allocation action is divided into different spaces according to threads, that is, each thread preallocates a piece of memory in the Java heap, becoming a local thread allocation buffer TLAB. Which thread wants to allocate memory is allocated on that thread's TLAB, and synchronous locking is only required when the TLAB is used up and the new TLAB is allocated.
Memory space initialization: After the memory allocation is completed, the virtual machine initializes allocated memory space to zero value (excluding the object header, the specific content of the allocated memory space will be explained in the next part). If TLAB is used, this work can be performed in advance until the TLAB allocation. This operation ensures that the object's instance field can be used directly without assigning the initial value in Java, that is, zero value.
Object header settings: Next, the virtual machine needs to make necessary settings for the object, such as: Which class instance is it? How to find the metadata information of a class? Hash code? GC of the subject is divided into age, etc. This information is stored in the object header of the object.
Initialization: From the perspective of virtual machine, a new object has been generated, but from the perspective of Java programs, this has just begun, because the data content in the memory is zero value. After executing new, the <init> method will be executed and initialized according to the programmer's requirements.
2. Memory layout of objects
It is divided into three parts:
(1) Object header
①Storing the object's own runtime data, such as hash code, GC generation age, lock status flag, lock held by thread, biased thread ID, biased timestamp, etc. It is 32bit in 32-bit virtual machines, and 64bit in 64-bit virtual machines, which is officially called "Mark Word". However, the storage of runtime data required is too much, which actually exceeds 32bit or 64bit. However, the object header information is an additional storage cost that is independent of the data defined by the object itself. Considering the efficiency of the virtual machine, Mark Word is designed as a non-fixed data structure to store as much information as possible in a very small space, it will reuse its own storage space according to the state of the object. For example, in a 32-bit HotSpot virtual machine, if the object is in an unlocked state, then the information related to the lock is not stored. The 25-bit store hashcode, the 4-bit store GC, the 2-bit store lock flag bit, and the 1-bit is fixed to 0.
② Type pointer, that is, an example of an object pointing to its class metadata. The virtual machine uses this pointer to determine which class the object is. Not all virtual machine implementations must retain type pointers on the data (related to object access positioning, as explained below). If the object is a Java array, there must be a piece in the object header to record the data of the array length, because the size of the array cannot be determined from the metadata of the array.
(2) Instance data
The valid information truly stored by the object is also the content of various types of field content defined in the program code. Whether it is inherited from the parent class or defined in the subclass, it must be recorded. The storage order of this part will be related to the virtual machine allocation policy parameters (FieldAllocationStyle) and the order in which fields are defined in the Java source code. The default allocation policies of HotSpot virtual machines are: longs/doubles, ints, shorts/chars, bytes/booleans, oop(Ordinary Object Pointers). From the policy, it can be seen that fields of the same width are always assigned together. On the premise that this is satisfied, the variables defined in the parent class will appear before the subclass. If the CompactFields parameter value is true (the default is true), then narrower variables in the subclass may also be inserted into the space of the parent class variable.
(3) Alignment fill
It does not exist necessarily, nor has a special meaning, it is just the role of placeholders. Since the automatic memory management of HotSpot VM must require the object's starting address to be an integer multiple of 8 bytes, in other words, the memory size of the object must be an integer multiple of 8 bytes. If it is insufficient, it will be filled to an integer multiple of 8.
3. Object access positioning
That is, how references in stack memory access objects in heap memory. There are two mainstream methods at present:
(1) Use handle:A region is divided into the Java heap as a handle pool. The stack stores the handle address of the object, and the handle contains the object instance data pointer (pointing to the heap memory) and the type data pointer (pointing to the method area).
(2) Direct pointer:The object address is directly stored in the stack, and the layout of the objects in the heap must include object sample data and type data pointers (pointing to the method area).
Advantages of using handles:The stable handle address stored in a reference, when the object is moved (moving the object is very common during garbage collection), will only change the instance data pointer of the handle, and the reference itself will not change.
Advantages of direct pointers:The speed is fast, saving time and overhead for pointer positioning at one time. Since object access is very frequent, it is also a considerable execution cost after very few objects. The HotSpot virtual machine uses the second type for object access.
3. Practical combat: OOM abnormality
The original book explains several ways and simple codes to generate several exceptions, and specifically refers to the content of the original book.
The above article briefly discusses the creation process of Java memory area and object is all the content I share with you. I hope you can give you a reference and I hope you can support me more.