Runtime data area
During the execution of Java programs, the Java VIRTUAL machine divides the memory it manages into different data areas. Each of these regions has its own purpose and time of creation and destruction. Some regions exist with the start of a virtual machine process, while others are created and destroyed depending on the start and end of a user thread. According to the Java Virtual Machine Specification (Java SE Version 7), the memory managed by the Java Virtual Machine will contain the following run-time data areas, as shown in figure 7.
Program counter
The Program Counter Register is a small memory space that can be thought of as a line number indicator of the bytecode being executed by the current thread. In the concept of virtual machine model (just the conceptual model, all kinds of virtual machine may be through some of the more efficient way to achieve), bytecode interpreter to work is by changing the counter value to select a need to be performed under the bytecode instruction, branches, loops, jumps, exception handling, thread to restore the basic function such as all need to rely on the counter. Because multithreading in the Java VIRTUAL machine is implemented by the way threads alternate and allocate processor execution time, at any given moment, one processor (or kernel for multi-core processors) will execute instructions in only one thread. Therefore, in order to recover to the correct execution position after thread switching, each thread needs to have an independent program counter, which is not affected by each other and stored independently. We call this kind of memory area “thread private” memory. If the thread is executing a Java method, this counter records the address of the virtual machine bytecode instruction being executed. If the Native method is being executed, this counter value is null (Undefined). This memory region is the only one where the Java Virtual Machine specification does not specify any OutOfMemoryError cases.
Java virtual machine stack
Like program counters, the Java Virtual Machine Stack is thread-private and has the same lifetime as a thread. The virtual machine Stack describes the memory model of Java method execution: each method execution creates a Stack Frame to store information about local variables, operand stacks, dynamic links, method exits, and so on. The process of each method from invocation to completion corresponds to the process of a stack frame being pushed into and out of the virtual machine stack. Java memory is often divided into Heap and Stack memory, which is a crude division, and the division of Java memory regions is actually much more complex than that. The popularity of this partition only shows that most programmers care most about these two areas of memory that are most closely related to the allocation of object memory. The “stack” referred to is the virtual machine stack, or the local variable table part of the virtual machine stack. The local variable table stores basic data types known at compile time (Boolean, byte, char, short, int, float, long, double), object references (reference type, which is not equivalent to the object itself, may be a reference pointer to the object’s starting address. They can also point to a handle representing an object or other location associated with that object) and the returnAddress type (which points to the address of a bytecode instruction). 64-bit long and double data occupy two local variable slots, and the rest occupy only one. The memory space required for the local variable table is allocated at compile time. When entering a method, how much local variable space the method needs to allocate in the frame is completely determined, and the size of the local variable table does not change during the method run. In the Java Virtual Machine specification, two exceptions are specified for this area: a StackOverflowError is thrown if the stack depth of a thread request is greater than the depth allowed by the virtual machine; If the virtual stack can be dynamically extended (as most Java virtual machines currently do, although the Java Virtual Machine specification also allows fixed-length virtual stacks), an OutOfMemoryError will be thrown if sufficient memory cannot be allocated during the extension.
Local method stack
The Native Method Stack is very similar to the virtual machine Stack. The difference is that the virtual machine Stack performs Java methods (that is, bytecode) services for the virtual machine, while the Native Method Stack serves the Native methods used by the virtual machine. The virtual machine specification does not mandate the language, usage, or data structure of methods in the local method stack, so specific virtual machines are free to implement it. There are even virtual machines (such as the Sun HotSpot VIRTUAL machine) that simply merge the local method stack with the virtual machine stack. Like the virtual stack, the local method stack area throws StackOverflowError and OutOfMemoryError exceptions.
The Java heap
For most applications, the Java Heap is the largest chunk of memory managed by the Java virtual machine. The Java heap is an area of memory that is shared by all threads and is created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and almost all object instances are allocated memory here. This is described in the Java Virtual Machine specification as follows: All object instances and arrays are allocated on the heap, but as JIT compilers and escape analysis techniques mature, allocation on the stack and scalar replacement optimization techniques can lead to subtle changes that make it less “absolute” to allocate all objects on the heap. The Java Heap is the primary area managed by the Garbage collector, so it is often referred to as the “Garbage Collected Heap”. From the point of view of memory collection, the Java heap can be subdivided into: new generation and old generation; More detailed are Eden space, From Survivor space, To Survivor space, etc. From the perspective of memory Allocation, the Java heap shared by threads may have multiple Thread private Allocation buffers (TLabs). However, no matter how to partition, it has nothing to do with the storage content, no matter which area, the storage is still the object instance, the purpose of further partition is to better reclaim memory, or faster allocation of memory. We will only discuss the role of memory regions; the details of allocation, reclamation, and so on for each of the above regions in the Java heap will be discussed. According to the Java Virtual Machine specification, the Java heap can be in a physically discontinuous memory space, as long as it is logically contiguous, like our disk space. When implemented, it can be either fixed size or extensible, but most current virtual machines are implemented as extensible (controlled by -xmx and -xMS). OutOfMemoryError is thrown if there is no memory in the heap to complete the instance allocation and the heap can no longer be extended.
Methods area
The Method Area, like the Java heap, is an Area of memory shared by threads that stores information about classes loaded by the virtual machine, constants, static variables, code compiled by the just-in-time compiler, and so on. Although the Java Virtual Machine specification describes the method area as a logical part of the Heap, it has an alias called non-heap, which is supposed to distinguish it from the Java Heap. For developers who are used to developing and deploying applications on HotSpot virtual machines, many prefer to refer to method areas as “Permanent Generation”, which is essentially not equivalent. Simply because the Design team of the HotSpot VIRTUAL machine chose to extend GC generation collection to the method area, or to implement the method area using persistent generations, the HotSpot garbage collector can manage this part of memory as well as the Java heap, saving it the work of writing memory-management code specifically for the method area. For other virtual machines (BEA JRockit, IBM J9, etc.) there is no concept of a permanent generation. In principle, how to implement method areas is a virtual machine implementation detail and is not subject to the vm specification, but using persistent generations to implement method areas is not a good idea because it is more likely to run into memory overflow problems (persistent generations have -xx: MaxPermSize, J9 and JRockit should not be a problem as long as they do not touch the upper limit of the process’s available memory, such as 4 GB on 32-bit systems. And there are very few methods (such as String.Intern ()) that can cause different performance on different VMS for this reason. Therefore, for the HotSpot VIRTUAL machine, according to the official roadmap information, there is also a plan to abandon the permanent generation and gradually adopt Native Memory to implement the method area. In the HotSpot 1.7 released so far, The string constant pool that was placed in the permanent generation has been removed. The Java Virtual Machine specification is very relaxed about method areas, which, like the Java heap, do not require continuous memory and can be either fixed size or extensible, but optionally do not implement garbage collection. Garbage collection is relatively rare in this area, but it is not as “permanent” as the name of the permanent generation that data enters the method area. The target of memory reclamation in this area is mainly for constant pool reclamation and type unloading. Generally speaking, the “performance” of the reclamation in this area is not satisfactory, especially for type unloading, but the reclamation in this part of the area is indeed necessary. Several serious bugs on Sun’s BUG list have been memory leaks caused by earlier versions of the HotSpot VIRTUAL machine not fully reclaiming this area. According to the Java Virtual Machine specification, OutOfMemoryError is thrown when the method area cannot meet memory allocation requirements.
Run-time constant pool
The Runtime Constant Pool is part of the method area. The Constant Pool Table is used to store various literals and symbolic references generated at compile time. This part of the Constant Table is stored in the runtime Constant Pool after the Class is loaded into the method area. The Java Virtual Machine has strict rules on the format of each part of a Class file (including the constant pool, of course). Each byte must be used to store what data is accepted, loaded, and executed by the VIRTUAL machine. However, the Java Virtual Machine specification does not specify any details about runtime constant pools. Virtual machines implemented by different vendors can implement this memory area according to their needs. However, in general, in addition to storing symbolic references described in Class files, translated direct references are also stored in the runtime constant pool. Runtime constant pool relative to the Class file another important feature of the constant pool is dynamic, the Java language does not require constant must only compile time to produce, is not preset constant pool into the Class file content can enter method area runtime constant pool, runtime might also put new constants in a pool, One feature that developers use most often is the Intern () method of the String class. Since the runtime constant pool is part of the method area and is naturally limited by the method area memory, OutOfMemoryError is thrown when the constant pool can no longer claim memory.
Direct memory
Direct Memory is not part of the run-time data region of the virtual machine, nor is it defined in the Java Virtual Machine specification. But this part of memory is also frequently used and can cause OutofMemoryErrors, so we’ll cover it here. The NIO (New Input/Output) class was introduced in JDK 1.4, introducing a Channel and Buffer based I/O method that can allocate off-heap memory directly using Native libraries. It then operates through a DirectByteBuffer object stored in the Java heap as a reference to this memory. This can significantly improve performance in some scenarios because it avoids copying data back and forth between the Java heap and Native heap. Obviously, the allocation of native direct memory is not limited by the Size of the Java heap, but since it is memory, it is certainly limited by the size of the total native memory (including RAM and SWAP or paging files) and the addressing space of the processor. When configuring VM parameters, the server administrator sets parameters such as -xmx based on the actual memory. However, the direct memory is often ignored. As a result, the sum of memory regions exceeds the physical memory limit (both physical and operating system-level), and an OutOfMemoryError occurs during dynamic expansion.