Java memory overflow and java memory overflow

Source: Internet
Author: User

Java memory overflow and java memory overflow
Memory Area

During Java program execution, the Java Virtual Machine divides the memory it manages into several different data regions. The Java virtual machine specification divides the memory managed by the JVM into the following runtime data zones: Program counters, Java Virtual Machine stacks, local method stacks, Java stacks, and method zones. The following describes in detail the data types stored in each data zone.

Program counters

A small memory space, which is the row number indicator of the bytecode executed by the current thread, when the bytecode interpreter is working, the value of this counter is changed to select the next bytecode instruction to be executed. Basic functions such as branch, jump, and loop depend on it. Each thread has an independent program counter, and the counters between threads do not affect each other. Therefore, this region is private to the thread.

When the thread is executing a Java method, the counter records the address of the Virtual Machine bytecode instruction being executed. When the thread is executing the Native method (calling the local operating system method) the counter value is null. In addition, the memory region is the only region that specifies any OOM (memory overflow: OutOfMemoryError) Conditions in the Java Virtual Machine specification.

Java Virtual Machine Stack

This region is also private to the thread, and its lifecycle is the same as that of the thread. The Virtual Machine stack describes the Memory Model of Java method execution. Each method creates a stack frame when it is executed, stack is a data structure used to support continuous virtual machines for method calling and method execution. For the execution engine, only the stack frame at the top of the stack is valid in the active thread, which is called the current stack frame. The method associated with this stack frame is called the current method, all bytecode commands run by the execution engine only operate on the current stack frame. Stack frames are used to store local variable tables, operand stacks, dynamic links, method return addresses, and some additional information. When compiling program Code, the local variable table required in the stack frame and the full depth of the operand stack have been completely determined and written into the Code attribute of the method table. Therefore, the amount of memory allocated to a stack frame is not affected by variable data during the runtime, but only depends on the specific Virtual Machine implementation.

In the Java Virtual Machine specification, two exceptions are specified for this region:

  • If the stack depth requested by the thread is greater than the depth allowed by the virtual machine, an StackOverflowError error is thrown.
  • If the VM cannot apply for sufficient memory space when dynamically scaling the stack, an OutOfMemoryError error is thrown.

These two situations overlap: When the stack space cannot be further allocated, whether the memory is too small or the used stack space is too large, in essence, it is only a description of the same thing. In single-threaded operations, whether the stack frame is too large or the VM stack space is too small, when the stack space cannot be allocated, the VM throws StackOverflowError and does not get the OutOfMemoryError exception. In a multi-threaded environment, an OutOfMemoryError is thrown.

The following describes in detail the role and data structure of each part of the information stored in the stack frame.

1. Local variable table

A local variable table is a storage space for variable values. It is used to store local variables defined in method parameters and methods, the types of stored data are the various basic data types, object references, and returnAddress types known during the compilation period (which point to the address of a bytecode instruction ). The memory space required for the local variable table is allocated during compilation. That is, when the Java program is compiled into a Class file, the maximum capacity of the local variable table to be allocated is determined. When you enter a method, the size of the local variable space allocated in the stack is completely determined, and the local variable table size will not be changed during the method running.

The local variable table capacity is measured in the smallest unit of Slot. The VM specification does not explicitly specify the memory space occupied by a Slot (which may vary with the processor, operating system, or virtual machine ), A Slot can store a data type of up to 32 bits: boolean, byte, char, short, int, float, reference, and returnAddresss. Reference is the reference type of an object. returnAddress serves byte instructions and executes the address of a bytecode instruction. For 64-bit data types (long and double), the virtual opportunity allocates two consecutive Slot spaces for them in the form of a high position.

The virtual machine uses the local variable table by means of index positioning. The index value ranges from 0 to the maximum number of slots in the local variable table. For 32-bit data-type variables, index n indicates the nth Slot. For 64-bit, index n indicates the nth Slot and the nth + 1 Slot.

During method execution, the virtual machine uses a local variable table to pass parameter values to the Parameter Variable list. If the instance method is not static ), the Slot of the 0th-bit index in the local variable table is used by default to pass the reference of the object instance to which the method belongs. In the method, you can use the keyword "this" to access this implicit parameter. Other parameters are arranged in the order of the parameter table, occupying the local variable Slot starting from 1. After the parameter table is allocated, other slots are allocated according to the variable sequence and scope defined in the method body.

Slots in the local variable table can be reused. The variables defined in the method body do not necessarily overwrite the entire method body, if the value of the current bytecode PC counter exceeds the scope of a variable, the Slot corresponding to this variable can be used by other variables. This design is not only designed to save space. In some cases, the reuse of slots directly affects the system and garbage collection.

2. operand Stack

The operation stack is also known as the operation stack. the maximum depth of the Operation stack is determined during compilation. The stack capacity of the 32-bit data type is 1. The stack capacity of the 64-bit data type is 2. When a method starts to be executed, its operation stack is empty. during the execution of the method, There will be various bytecode commands (such as adding operations and assigning values to meta calculation) write and extract content to and from the Operation stack, that is, the inbound and outbound operations.

The interpreted execution engine of a Java virtual machine is called the stack-based execution engine. The stack refers to the operand stack. Therefore, we also call Java virtual machines stack-based. This is different from Android virtual machines, Where Android virtual machines are register-based.

The main advantage of stack-based instruction sets is high portability, and the main disadvantage is that the execution speed is relatively slow. Because registers are directly provided by hardware, therefore, the main advantage of the register-based instruction set is that the execution speed is fast, and the main disadvantage is poor portability.

3. Dynamic connection

Each stack frame contains a reference to the method to which the stack frame belongs in the runtime volume pool (described later in the method area, hold this reference to support dynamic connections during method calls. A large number of symbolic references exist in the constant pool of the Class file. The method call instruction in the bytecode takes the symbolic reference pointing to the method in the constant pool as the parameter. Some of these symbolic references will be converted to direct references (such as final and static domains) during the class loading stage or when used for the first time. These are called static parsing, the other part will be converted to direct reference during each running period, which is called dynamic connection.

4. Method return address

After a method is executed, there are two ways to exit the method: the execution engine encounters the bytecode command returned by any method or encounters an exception, the exception is not handled in the method body. No matter which exit method is used, after the method exits, it must be returned to the location where the method is called before the program can continue execution. When the method returns, you may need to save some information in the stack frame to help restore the execution status of its upper method. Generally, when the method Exits normally, the caller's PC counter value can be used as the return address. This counter value may be saved in the stack frame, and when the method exits unexpectedly, the returned address is determined by the exception processor. This information is generally not stored in stack frames.

The exit process of the method is actually equivalent to putting the current stack frame out of the station. Therefore, the operations that may be performed during exit include restoring the local variable table and the operand stack of the upper method. If there is a return value, then it is pushed into the operator stack of the caller stack frame, and the PC counter value is adjusted to point to a command after the method call command.

Local method Stack

This region is very similar to the Virtual Machine stack, except that the virtual machine stack executes Java method services for the virtual machine, while the local method stack serves the Native method used.

Java heap

Java Heap is the largest part of the memory managed by the Java Virtual Machine. It is a memory area shared by all threads. Almost all object instances and arrays are allocated with memory. Java Heap is the main area for managing the Garbage Collector. Therefore, it is often called a "GC Heap ".

According to the Java Virtual Machine specification, the Java heap can be in physically discontinuous memory space, as long as the logic is continuous. If no memory can be allocated in the heap and the heap cannot be extended, an OutOfMemoryError will be thrown.

Method Area

The method area is also the memory area shared by various threads. It is used to store data such as class information, constants, static variables, and Code Compiled by the real-time compiler. The method area is also called "permanent generation", but for Sun HotSpot alone, the concept of permanent generation does not exist in JRockit and IBM J9 virtual machines. Java Virtual Machine specifications describe the method area as a logical part of the Java Heap, and it does not need continuous memory like Java Heap. You can choose a fixed size or scalable. In addition, the virtual machine specification allows the region to choose not to recycle garbage. Relatively speaking, the garbage collection behavior rarely appears in this area. The main aim of memory recycle in this region is to recycle discarded constants and useless classes. The runtime constant pool is part of the Method Area. In addition to the Class version, field, method, interface, and other description information, the Class file, another information is the constant pool (the constant pool of the Class file), which is used to store various literal quantities and symbol references generated by the compiler, this part of the content will be stored in the method zone runtime pool after the class is loaded. Another important feature of the runtime constant pool relative to the Class file constant pool is that it is dynamic. Java does not require constants to be generated only during compilation, that is to say, it is not the content of the constant pool preset into the Class file that can enter the runtime constant pool in the method area. During the runtime, new constants may also be placed in the pool, developers exploit this feature to use the intern () method of the String class.

According to Java Virtual Machine specifications, when the method area cannot meet the memory allocation requirements, an OutOfMemoryError exception will be thrown.

Direct Memory

Direct Memory is not part of the data zone of the Virtual Machine runtime, nor is it the memory zone defined in the Java Virtual Machine specification. It is directly allocated from the operating system, so it is not limited by the Java heap size, however, it is limited by the total memory size of the local machine and the addressing space of the processor. Therefore, it may also cause an OutOfMemoryError error. The NIO mechanism is introduced in JDK1.4. It is a new I/O Method Based on channels and buffers. It can be directly allocated from the operating system, that is, the memory is allocated outside the heap, this can improve performance in some scenarios, because it avoids data replication back and forth between the Java heap and the Native heap.

Memory Overflow

Below is a simple test method for memory overflow in the memory area.

It is important to note that, in the case of multiple threads, the larger the memory allocated to each thread stack, the more likely the memory overflow exception will occur. The operating system limits the memory allocated to each process. The virtual machine provides parameters to control the maximum memory of the Java heap and method areas, ignore the memory consumed by the program counter (small) and the memory consumed by the process itself. The remaining memory is allocated to the Virtual Machine stack and local method stack. The larger the stack Capacity allocated by each thread, the fewer threads you can create. Therefore, if the memory overflow is caused by too many threads, the number of threads cannot be reduced, you can only reduce the maximum heap and the stack capacity of each thread in exchange for more threads.

In addition, Memory leakage (Memory Leak) may also occur in the Java heap. Here we will briefly describe the differences between Memory leakage and Memory overflow:

Memory leakage means that the allocated memory is not recycled, and the resource is wasted due to the loss of control over the memory area. Java generally does not cause memory leakage, because garbage collector automatically recycles garbage, but this is not absolute. When we create an object and save its reference, we will never use it later, the garbage collector will not recycle it, which will cause memory leakage,

Memory overflow means that the memory required by the program exceeds the upper limit of the memory (including dynamic expansion) that the system can allocate.

Object Instantiation Analysis

The most common example of memory allocation analysis is Object Instantiation:

Object obj = new Object();

The execution of this Code involves the three most important memory areas: Java stack, Java heap, and method zone. Assuming that this statement appears in the method body and is used in Java that is not known to the JVM virtual machine in a timely manner, you should also know that obj will be used as a reference type) the data is stored in the local variable table of the Java stack, but the referenced instantiated object will be saved in the Java stack, but it may not be known, the Java heap must also contain the address information (such as the object type, parent class, implemented interface, and method) that can be used to locate the data of this object type ), these types of data are stored in the method area.

In addition, because the reference type only specifies a reference pointing to an object in the Java Virtual Machine specification, it does not define the method in which the reference should be located, and the specific location of the object accessed to the Java heap. Therefore, object access methods implemented by different virtual machines are different. There are two mainstream access Methods: Using the handle pool and directly using pointers.

Access through the handle pool is as follows:

Direct pointer access is as follows:

The two object access methods have their own advantages. The biggest advantage of using the handle access method is that the reference stores a stable handle address, when an object is moved (moving objects during garbage collection is a very common behavior), it only changes the instance data pointer in the handle, and the reference itself does not need to be modified. The biggest advantage of direct pointer access is fast speed, which saves the time overhead of one pointer location. Currently, the HotSpot Virtual Machine Used by Java by default adopts the second method for object access.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.