Home >Java >javaTutorial >Detailed introduction to Java memory areas and memory overflow exceptions

Detailed introduction to Java memory areas and memory overflow exceptions

黄舟
黄舟Original
2017-03-17 10:18:411361browse

This article mainly introduces the relevant information about Java memory area and memory overflow exception. Friends who need it can refer to

Java memory area and memory overflow exception

Overview

For developers who develop C and C++ programs, in the field of memory management, programmers have absolute rights to use memory, but they must also The main thing is to use and clean up memory correctly, which requires programmers to have a higher level.

For Java programmers, with the help of the virtual machine's automatic memory management mechanism, there is no longer a need to write paired delete/free code for each new operation, and memory leaks and Memory overflow problem, it seems that everything is fine with the virtual machine managing the memory. However, it is precisely because Java programmers have given the power of memory control to the Java virtual machine. Once problems with memory leaks and overflows occur, if you do not understand how the virtual machine uses memory, troubleshooting will become a task. Extremely difficult work.

Java runtime data area

We generally think that the JVM is composed of two parts: the heap and the stack, but the actual Java virtual machine executes the Java program. In the process, the memory it manages is divided into several different data areas. These areas have their own purposes, as well as the time of creation and destruction. Some areas exist with the startup of the virtual machine process, and some areas are created and destroyed depending on the start and end of the user thread. As shown below:

Program Counter

If you have studied the principles of computer composition, it should be clear that the program counter is equivalent to an ID card Similarly, since the JVM also has its own CPU, when executing a multi-threaded program, it schedules thread execution according to the program counter through time slice rotation.

The program counter (Program Counter Register) is a small memory space. Its function can be regarded as a line number indicator of the bytecode executed by the current thread. In the conceptual model of the virtual machine (only a conceptual model, various virtual machines may be implemented in more efficient ways), the bytecode interpreter works by changing the value of this counter to select the next step that needs to be executed. Bytecode instructions, branches, loops, jumps, Exception handling, thread recovery and other basic functions all need to rely on this counter to complete.

Since the multi-threading of the Java virtual machine is implemented by switching threads in turns and allocating processor execution time, at any certain moment, a processor (for a multi-core processor, a core ) will only execute instructions in one thread. Therefore, in order to return to the correct execution position after thread switching, each thread needs to have an independent program counter. The counters between each thread do not affect each other and are stored independently. We call this type 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 thread is executing a Natvie method, the counter value is empty (Undefined) . This memory region is the only one in which the Java Virtual Machine Specification does not specify any OutOfMemoryError conditions.

Java Virtual Machine Stack

Like the program counter, the Java Virtual Machine Stacks (Java Virtual Machine Stacks) are also thread-private, and its life cycleSame as thread.

The virtual machine stack describes the memory model of Java method execution: when each method is executed, a stack frame (Stack Frame) will be created at the same time to store local variables Tables, operation stacks, dynamic links, method exports and other information. The process from each method being called until execution is completed corresponds to the process of a stack frame being pushed from the stack to being popped out of the stack in the virtual machine stack.

Some people often divide Java memory into heap memory (Heap) and stack memory (Stack). This division is relatively rough. The division of Java memory areas is actually far more complicated than this. The popularity of this division method only shows that the memory areas that most programmers pay most attention to and are most closely related to object memory allocation are these two areas. The "heap" referred to will be discussed specifically later, and the "stack" referred to is the virtual machine stack we are talking about now, or the local variable table part of the virtual machine stack.

The local variable table stores various basic data types (boolean, byte, char, short, int, float, long, double), object references ( reference type, which is not equivalent to the object itself. According to different virtual machine implementations, it may be a reference pointer pointing to the starting address of the object, or it may point to a handle representing the object or other locations related to this object) and returnAddress type (Points to the address of a bytecode instruction).

The 64-bit long and double type data will occupy 2 local variable spaces (Slots), and the other data types will only occupy 1. The memory space required by the local variable table is allocated during compilation. When entering a method, it is completely determined how much local variable space this method needs to allocate in the frame. The size of the local variable table will not change during the running of the method.

In the Java virtual machine specification, two exception conditions are specified for this area: if the stack depth requested by the thread is greater than the depth allowed by the virtual machine, a StackOverflowError exception will be thrown; if the virtual machine stack can be dynamically expanded (Most current Java virtual machines can be dynamically expanded, but the Java virtual machine specification also allows fixed-length virtual machine stacks.) When expansion cannot apply for enough memory, an OutOfMemoryError exception will be thrown.

Native method stack

The functions played by native method stacks (Native Method Stacks) and virtual machine stacks are very similar. The only difference is that the virtual machine stack is The virtual machine executes Java method (that is, bytecode) services, and the local method stack serves the Native methods used by the virtual machine. The virtual machine specification does not mandate the language, usage, and data structure of methods in the local method stack, so specific virtual machines can implement it freely. Some virtual machines (such as the Sun HotSpot virtual machine) even directly combine the local method stack and the virtual machine stack into one. Like the virtual machine stack, the local method stack area also throws StackOverflowError and OutOfMemoryError exceptions.

Java Heap

For most applications, the Java Heap (Java Heap) is the largest piece of memory managed by the Java virtual machine. The Java heap is a memory area shared by all threads and is created when the virtual machine starts. The only purpose of this memory area is to store object instances, and almost all object instances allocate memory here. This is described in the Java virtual machine specification as follows: All object instances and arrays must be allocated on the heap. However, with the development of JIT compilers and the gradual maturity of escape analysis technology, allocation on the stack and scalar replacement optimization technology will This will lead to some subtle changes, and all objects allocated on the heap will gradually become less "absolute".

ava The heap is the main area managed by the garbage collector, so it is often called the "GC Heap (" Garbage Collected Heap, fortunately, it is not translated into "garbage heap" in China). From the perspective of memory recycling, since current collectors basically use generational collection algorithms, the Java heap can also be subdivided into: new generation and old generation; more detailed ones include Eden space, From Survivor space, To Survivor space etc. From the perspective of memory allocation, the thread-shared Java heap may be divided into multiple thread-private allocation buffers (Thread Local Allocation Buffer, TLAB). However, no matter how divided it is, it has nothing to do with the stored content. No matter which area, object instances are still stored. The purpose of further dividing is to better recycle memory or allocate memory faster. In this chapter, we only discuss the role of the memory area. The details of the allocation and recycling of the above areas in the Java heap will be the subject of the next chapter.

According to the Java Virtual Machine Specification, the Java heap can be in physically discontinuous memory space, as long as it is logically continuous, just like our disk space. When implemented, it can be implemented as either a fixed size or scalable, but the current mainstream virtual machines are all implemented as scalable (controlled by -Xmx and -Xms). If there is no memory in the heap to complete the instance allocation, and the heap can no longer be expanded, an OutOfMemoryError exception will be thrown.

Method Area

The Method Area, like the Java heap, is a memory area shared by each thread. It is used to store classes that have been loaded by the virtual machine. Information, constants, static variables, code compiled by just-in-time compiler and other data. Although the Java virtual machine specification describes the method area as a logical part of the heap, it has an alias called Non-Heap (non-heap), and the purpose should be to distinguish it from the Java heap.

The Java virtual machine specification has very loose restrictions on this area. In addition to not requiring contiguous memory like the Java heap and having the option of fixed size or expandability, you can also choose not to implement garbage collection. Relatively speaking, garbage collection behavior is relatively rare in this area, but it does not mean that the data entering the method area exists "permanently" like the name of the permanent generation. The memory recycling target in this area is mainly for the recycling of constant pools and the unloading of types. Generally speaking, the recycling "scores" of this area are relatively unsatisfactory, especially for the unloading of types. The conditions are quite harsh, but the Recycling is indeed necessary.

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

Runtime Constant Pool

The Runtime Constant Pool (Runtime Constant Pool) is part of the method area.

Class In addition to the class version, fields, methods, interfaces and other description information, there is also a constant pool (Constant Pool Table), which is used to store various literals generated during compilation. and symbol references, which will be stored in the runtime constant pool in the method area after the class is loaded.

The Java virtual machine has strict regulations on the format of each part of the Class file (naturally including the constant pool). What kind of data each byte is used to store must comply with the specification requirements, so that It will be recognized, loaded and executed by the virtual machine. But for the runtime constant pool, the Java virtual machine specification does not make any detailed requirements. Virtual machines implemented by different providers can implement this memory area according to their own needs. However, generally speaking, in addition to saving the symbol references described in the Class file, the translated direct references are also stored in the runtime constant pool.

Another important feature of the runtime constant pool compared to the Class file constant pool is that it is dynamic. The Java language does not require constants to be generated only during compilation, that is, they are not preset in the Class file. Only the contents of the pool can enter the runtime constant pool in the method area. New constants may also be put into the pool during runtime. This feature is often used by developers is the intern() of the

String class. method.

Since the runtime constant pool is part of the method area, it will naturally be limited by the memory of the method area. When the constant pool can no longer apply for memory, an OutOfMemoryError exception will be thrown.

Direct memory

Direct memory (Direct Memory) is not part of the virtual machine runtime data area, nor is it a memory area defined in the Java virtual machine specification, but This part of memory is also frequently used, and may also cause OutOfMemoryError exceptions.

The NIO (New Input/Output) class was newly added to JDK 1.4, and an I/O method based on channel (Channel) and buffer (Buffer) was introduced, which can directly use the Native function library Allocate off-heap memory, and then operate 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 the Native heap.

Obviously, the allocation of local direct memory will not be limited by the size of the Java heap. However, since it is memory, it will definitely be affected by the size of the total local memory (including RAM and SWAP area or paging file). and processor addressing space limitations. When server administrators configure virtual machine parameters, they generally set -Xmx and other parameter information based on the actual memory, but often ignore direct memory, making the sum of each memory area greater than the physical memory limit (including physical and operating system-level limits) ), resulting in an OutOfMemoryError exception during dynamic expansion.

The above is the detailed content of Detailed introduction to Java memory areas and memory overflow exceptions. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn