In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
In this issue, the editor will bring you about how to understand the JVM memory structure in the Java virtual machine. The article is rich in content and analyzes and narrates it from a professional point of view. I hope you can get something after reading this article.
Preface
JVM is a part of Java that is difficult to understand and master, and it is also asked more in the interview. Mastering the underlying principles of JVM will help us to write more efficient code in development, so that we can no longer look confused in the face of OutOfMemoryError. We can use our JVM knowledge to find and analyze problems, to optimize JVM, to make our applications support higher concurrency, and so on. In a word, it is very important to learn JVM well!
What is JVM?
JVM is the abbreviation of Java Virtual Machine (Java Virtual Machine). JVM is a specification for computing devices. It is a fictional computer, which is realized by simulating various computer functions on a real computer. Note that JVM is based on software, not hardware.
A very important feature of Java language is its platform independence. The use of Java virtual machine is the key to realize this feature. If a general high-level language is to run on different platforms, it needs to at least be compiled into different object code. After introducing the Java language virtual machine, the Java language does not need to be recompiled when it runs on different platforms. The Java language uses the pattern Java virtual machine to shield the information related to the specific platform, so that the Java language compiler only needs to generate the object code (bytecode) running on the Java virtual machine and can run on a variety of platforms without modification. When executing the bytecode, the Java virtual machine interprets the bytecode as the execution of machine instructions on the specific platform.
For example, the following figure: we compiled the .class file is binary bytecode, bytecode can not be directly run by the machine, through JVM to convert the compiled bytecode into the corresponding operating system platform can directly identify the machine code instructions, JVM acts as an intermediate conversion bridge, so that we can write the Java file can be "compiled, run everywhere".
Overview of JVM memory structure
JVM virtual machine specification official document address: https://docs.oracle.com/javase/specs/ JK 8 virtual machine reference manual address: https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/index.html Magi JDK 8 official document address is https://docs.oracle.com/javase/8/docs/ Magi JDK 8 memory structure document https://docs.oracle.com/javase/specs/jvms/se8/html/index.html.
Let's take a look at the following picture (this picture is very important! It's very important! It's very important! ), the execution process of a Java file is as follows: the Hello.java file is compiled into a Hello.class file through javac, and then the class loading subsystem loads the class file into the runtime data area and executes the generated machine instructions through the execution engine.
During the execution of the Java program, the Java virtual machine divides the memory it manages into several different data areas, which is called the runtime data area. The runtime data area mainly includes PC register (program counter), Java virtual machine stack, local method stack, Java stack, method area and runtime constant pool, in which Java stack, method area and Java virtual machine stack are the focus of learning.
However, it should be noted that the above region division is only logical regions, and the restrictions on some areas are relatively loose, so different virtual machine manufacturers are different in implementation, even different versions of the same virtual machine.
Runtime datazone program counter
The program counter (Program counter Register, also known as the PC register) is a small piece of memory that is private to the thread and can be seen as a line number indicator of the bytecode executed by the current thread. In the conceptual model of virtual machines (only conceptual models, various virtual machines may be implemented in more efficient ways), when the bytecode interpreter works, the bytecode interpreter selects the next bytecode instruction to be executed by changing the value of this counter. Basic functions such as branching, loop, jump, exception handling, thread recovery and so on depend on this counter. Because Java can be executed by multiple threads, one thread may be private because the CPU time wheel is switched to another thread, and when switching back to the previous thread, it needs to return to the thread's last execution position.
If the thread is executing a Java method, the counter records the address of the executing virtual machine bytecode instruction; if the Native method is being executed, the counter value is Undefined. This memory zone is the only area that does not specify any OutOfMemoryError wishes in the Java virtual machine specification.
For example, in the following code, test2 () is called in test1 (), and test2 () exits after execution is completed. At this point, you need to go back to the test1 () method to continue execution, and the program counter records the line number of the next instruction to be executed.
Public void test1 () {test2 (); System.out.println ("test1");} public void test2 () {System.out.println ("test2");} Java virtual machine stack
The Java virtual machine stack (Java Virtual Machine Stacks) is also thread-private and has the same life cycle as threads. Virtual machine stack describes the memory model of Java method execution: each method creates a stack frame (Stack Frame) to store local tables, Operand stacks, dynamic links, method exits, and so on. Stack frame is the basic data structure of Java method runtime. The process of each method from call to execution corresponds to the process of stack frame from stack to unstack in the virtual stack (human talk is to execute a method, press the stack frame of the method into the top of the stack, and the method execution completes its stack frame off the stack). In JVM, there are only two operations for stack frames: off-stack and on-stack. The method being executed by the thread is called the current thread method, and the stack frame of the method is called the current frame.
The local variable table stores various basic data types known at compile time (boolean, byte, char, short, int, long, float, double), object reference (reference type, which is not equivalent to the object itself, may be a reference pointer to the starting address of the object, or it may point to a handle on behalf of the object or its location associated with the object) and the returnAddress type (the address that points to a bytecode instruction).
In the Java virtual machine specification, there are two different conditions for this area: if the depth of the stack requested by the thread is greater than the depth allowed by the virtual machine, a StackOverFlowError exception will be thrown; the general virtual machine stack is scalable, and if it cannot be expanded with enough memory, it will throw an OutOfMemoryError exception, and the stack size of each thread can be set by-Xss.
The structure of the Java virtual machine stack is shown in the following figure: the life cycle of the Java virtual machine stack is consistent with that of the thread. A method corresponds to a memory area of a stack frame, which contains local variable table, Operand stack, dynamic link, method exit and other information. Take the following code as an example, the program executes main (), main () is pressed into the top of the stack first, and then a Math object is new in the main () method. The math variable is a reference to the Math object in the stack, and the math variable belongs to the local variable table. After the Math object is created, its compute () is called, and then compute () is pressed into the top of the stack. After the compute method is executed, the stack frame is released from the stack, and then the line number of the program execution is recorded according to the program counter. If we go back to the execution of the main method, and there are no other execution instructions in the main method, the main method exits, the stack frame corresponding to the main method goes out of the stack, there are no other stack frames in the virtual machine stack, and the life cycle of the main thread ends.
Note: with regard to the stack frames in the Java virtual machine stack, as well as the components of the stack frames, this is just a simple overview, which will be explained in detail later. I hope to continue to pay attention to it.
Public class Math {private static final Integer CONSTANT=666; private int compute () {/ / A method corresponds to a stack frame memory area int axiom 3; int baud 5; int c = (aquib) * 10; return c } public static void main (String [] args) {Math math=new Math (); math.compute ();}}
Local method stack
The native method stack (Native Method Stack) is very similar to the virtual machine stack and is thread-private, except that the virtual machine stack executes the Java method (that is, bytecode), while the local method stack uses the Native method. It's like virtual machine warfare. StackOverFlowError and OutOfMemoryError exceptions also occur in the local method stack area.
Method area
The method area (Method Area), which is the memory area shared by each thread, is used to store data such as type information, constants, static variables, code cache compiled by the real-time compiler, which have been loaded by the virtual machine. Although the JVM specification describes the method area as a logical part of the heap, it also has an alias called Non-Heap (non-heap), which is intended to separate from the heap. This section stores the class-related information necessary for the runtime. The data loaded into this area will not be reclaimed by the garbage collector. The memory occupied by this area will be freed only if Jvm is closed.
For Hotspot virtual machines, many developers are accustomed to calling the method area "Parmanent Gen", but they are strictly different in nature, or use permanent generation to implement the method area, which is an implementation of the method area (equivalent to an interface interface). In the idkl.7 version, the original string constant pool of the permanent generation has been removed. The legal zone in Jdk1.7 is implemented in permanent generation. In 1.8, it is implemented in metaspace (MetaSpace), which uses direct memory.
According to the Java virtual machine specification, an OutOfMemoryError exception is thrown when the method zone cannot meet the memory allocation requirements. You can set the minimum and maximum space of the permanent zone through-XX:PermSize and-XX:MaxPermSize, respectively.
Running constant pool
The runtime constant pool (Runtime Constant Pool) is part of the method area. In addition to the version, field, method, interface and other description information of the class, another piece of information in the Class file is the constant pool, which is used to store all kinds of literals and symbol references produced during compilation. This part of the content is stored in the runtime pool of the method area after the class is loaded.
There are two main types of constants stored in the constant pool: literal quantities (Literal) and symbolic references (Symbolic References). Literals are close to the concepts of constants at the Java language level, such as text strings, constant values declared as final, and so on. Symbolic references, on the other hand, belong to the concept of compilation principles, including the following three types of constants:
Fully qualified name of the class and interface (Fully Qualified Name)
The name and descriptor of the field (Descriptor)
The name and descriptor of the method
When Java code compiles Javac, it does not have the step of "connect" like C and C++, but dynamically connects when the virtual machine loads the Class file. In other words, the final memory layout information of each method and field is not saved in the Class file, so the symbolic references of these fields and methods cannot get the real memory population address without runtime conversion, and cannot be directly used by the virtual machine. When the virtual machine is running, it needs to obtain the corresponding symbol reference from the constant pool, and then parse and translate to the specific memory address when the class is created or run.
The Java language does not require that constants must be generated only by the compiler, and the runtime may put new constants into the pool, which is more often used by the intern () method of the String class. The runtime pool is part of the method area, and an OutOfMemoryError exception is thrown when there is not enough memory.
Java reactor
For most applications, the Java heap (Java Heap) is the largest block of memory managed by the Java virtual machine. The Java heap is shared by threads and is created when the virtual machine starts. The sole purpose of this memory area is to store object instances, where almost all object instances allocate memory. This is described in the Java virtual machine specification: all object instances and arrays should be allocated on the heap, but with the development of JIT compiler and escape analysis technology gradually mature, stack allocation, scalar replacement optimization techniques will lead to some subtle changes, and all objects allocated on the heap gradually become less "absolute".
Java heap is the main area to be collected and managed, so it is often called "GC heap" (Garbage Collected Heap). From the point of view of memory collection, since the current collectors basically use generational algorithms (why do we use generational algorithms and which commonly used garbage collection algorithms will be described later), the heap is also subdivided into Young/New and Old/Tenure, which can be divided into Eden (Garden of Eden) space and survivor (survival area, which can be divided into from survivor and to survivor). That is, S0 and S1) spaces and so on. From the perspective of memory allocation, the Java heap shared by threads can be divided into private allocation buffers (Thread Local Allocation Buffer,TLAB) of multiple processes. However, no matter how the partition, it has nothing to do with the storage content, no matter which area, the storage is still the object instance, the further division is to better reclaim memory, or allocate memory faster.
According to the Java virtual machine specification, the Java heap can be in physically discontiguous memory space and can only be logically continuous. Java virtual machine can expand the heap by setting the starting heap size by-Xms, setting the maximum heap size by-Xmx, setting the minimum space size of the new generation by-XX:NewSize, and setting the maximum space size of the new generation by-XX:MaxNewSize. If the instance allocation is not completed in the heap and the ground can no longer be extended, an OutOfMemoryError exception will be thrown.
The following figure shows the Jvm memory partition in Java7:
Heap (Heap), permanent generation (PermGen)
Heap is divided into Cenozoic (NewGen) or younger generation (YoungGen) and older generation (OldGen).
The younger generation (YoungGen) can be divided into Eden area (Eden Park) and Survivor area (survival area).
The Survivor area (survival area) can be divided into FromSpace (S0) and ToSpace (S1). The default proportion of Eden:S0:S1=8:1:1 in the whole young generation is S0 and S1. Only one area is occupied at the same time.
Younger generation (New): the younger generation is used to store the Java objects just allocated by JVM.
Old: objects that are not recycled after garbage collection in the younger generation will be Copy to the older generation.
Permanent generation (Perm): permanent generation stores Class and method meta-information, which is related to the size, class and method of the project.
The GC that occurs in the younger generation is called Minor GC, and the GC that occurs in the old age is called Major GC.
There is also a Full GC that cleans up the entire heap space-including the younger and permanent generations
The generation of the heap and how the object moves from the younger generation to the old will be described in later chapters.
Let's take a look at the following diagram. In JDK1.8, the permanent generation is removed and the method area is implemented by MetaSpace. The biggest difference between metaspace and permanent generation is that it is not in JVM memory, but the direct memory used.
The method area, constant pool, and permanent generation have changed a lot in JDK6, 7, 8:
Jdk1.6 and before: permanent generation, constant pool 1.6 in the method area
Jdk1.7: there is a permanent generation, but it has been gradually "de-permanent". The constant pool is 1.7 in the heap.
Jdk1.8 and later: no permanent generation, constant pool 1.8 in metaspace
Direct memory
Direct memory (Direct Memory) is not part of the virtual machine runtime data zone, nor is it a memory area defined in the Java virtual machine specification. A new NlO (New Inpu/Output) class is added to JDK1.4, which introduces an IJDK1.4 O method based on channel (Channel) and buffer (Buffer). It can allocate out-of-heap memory directly using Native function library, 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 Native heap and the Java heap.
Obviously, the allocation of native direct memory is not limited by the Java heap size, but since it is memory, it is certainly limited by the size of the total native memory (including RAM and SWAP zones or paging files) and the processor addressing space. When the sum of each memory area is greater than the physical memory limit (including physical and operating system-level limits), it will cause an OutOfMemoryError exception during dynamic expansion.
The above is how to understand the JVM memory structure in the Java virtual machine. If you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.