In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "how to understand and master the Java virtual machine memory area", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to understand and master the Java virtual machine memory area.
1. Method area (Method Area)
The concept of method area
The method area, also known as the static zone, stores the basic information, constants, static variables, etc., of the loaded class. It is an area shared by threads.
For example, when we write Java code, each line level can access static variable objects of the same class. Due to the use of the reflection mechanism, it is difficult for the virtual machine to guess which type of information is no longer used, so it is difficult to recycle this area.
What is the difference between static blocks and non-static blocks?
What is the difference and relationship between Class and Object?
Why can't this and super keywords be used in static blocks?
Why can java's static methods be called directly with the class name?
Characteristics of the method area
Shared area between threads
Anomalies in the method area
This area is mainly for constant pool recycling, and it is worth noting that JDK1.7 has moved constant pools to the heap. Similarly, an OutOfMemoryError is thrown when the method area cannot meet the memory allocation requirements. Manufacturing method area memory overflow, note that method area overflow must be in JDK1.6 and previous versions. As explained later, the virtual machine parameters-XXpermSize and-XX:MaxPermSize can be used to limit the method area size before execution.
The code listing is as follows:
Public static void printOOM () {List list = new ArrayList (); int I = 0; while (true) {list.add (String.valueOf (I). Intern ());}}
Output exception result:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf (Arrays.java:2245) at java.util.Arrays.copyOf (Arrays.java:2219) at java.util.ArrayList.grow (ArrayList.java:242) at java.util.ArrayList.ensureExplicitCapacity (ArrayList.java:216) at java.util.ArrayList.ensureCapacityInternal (ArrayList.java:208) at java.util.ArrayList.add (ArrayList.java:440) at com.vprisk.knowledgeshare.MethodAreExample. Main (MethodAreExample.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0 (NativeMethod) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:606) at com.intellij.rt.execution.application.AppMain.main (AppMain.java:147)
About the role of the intern () function intern () of String:
If the current string does not exist in the constant pool, it is placed in the constant pool.
The above code keeps adding strings to the constant pool, which will eventually result in running out of memory and throwing the OOM of the method area. Explain why the above code must be run before JDK1.6. After we mentioned JDK1.7 earlier, we put the constant pool into the heap space, which leads to different functions of the intern () function, as shown in the code listing:
Public static void testInternMethod () {String str1 = new StringBuilder ("hua"). Append ("chao"). ToString (); System.out.println (str1.intern () = = str1); String str2=new StringBuilder ("ja"). Append ("va"). ToString (); System.out.println (str2.intern () = = str2);}
In the scene jdk6, output the result:
False, false
In the scene jdk7, output the result:
True, false
Why?
The reason is that in JDK 1.6, the intern () method copies the string instance encountered for the first time to the constant pool and returns a reference to the string in the constant pool, while the string instance created by StringBuilder is on the heap, so it must not be the same reference and returns false. In JDK 1.7, the intern method no longer replicates the instance, and only the reference to the instance that first occurs is saved in the constant pool, so the reference returned by intern () is the same as the string instance created by StringBuilder. Why does the comparison to str2 return false? This is because the string "java" already exists when the class is loaded internally in JVM, which does not conform to the principle of "first occurrence", so false is returned.
The role of the method area
The method area stores class information, constants, static variables, etc., and is the shared area of each thread.
Application of method area
Limit the method area size by setting the parameters of the virtual machine-XXpermSize and-XX:MaxPermSize.
Virtual Machine Stack (VM Stack)
The concept of virtual machine stack
The memory model executed by the Java method:
When each method is executed, a stack frame (StackFrame) is created to store local variables, operation stacks, dynamic links, method exits, and other information. The process in which each method is called until the execution is completed corresponds to the process of a stack frame in the virtual machine stack from the stack to the stack.
Local variable scale
The local variable table stores various basic data types (boolean, byte, char, short, int, float, long, double), object references (Object reference) and bytecode instruction addresses (returnAddress types) that the compiler controls.
Operation stack
Operand stack, also known as Operand stack, is a last-in, first-out (Last In First Out, LIFO) stack. Like the local variable table, the maximum depth of the Operand stack is written to the max_stacks data item of the Code property at compile time. Each element of the Operand stack can be any Java data type, including long and double. The stack capacity of 32-bit data types is 1. The stack capacity of 64-bit data types is 2. At any time when the method is executed, the depth of the Operand stack does not exceed the maximum set in the max_stacks data item.
When a method is just executed, the Operand stack of the method is empty. During the execution of the method, various bytecode instructions will write and extract content to the Operand stack, that is, the operation of entering and leaving the stack. For example, when doing arithmetic operations, it is done through the Operand stack, or when other methods are called, parameters are passed through the Operand stack.
For example, the bytecode instruction iadd for integer addition requires that the two elements closest to the top of the Operand stack have been stored in two int values. When this instruction is executed, the sum of the two int values will be added, and then the result of the addition will be added to the stack.
The data type of the elements in the Operand stack must strictly match the sequence of bytecode instructions, which should be strictly guaranteed by the compiler when compiling the program code, and should be verified again in the data flow analysis of the class check phase. Take the above iadd instruction as an example, this instruction is used for integer addition, and when it is executed, the data type of the two elements closest to the top of the stack must be int, and there can be no addition of a long and a float using the iadd command.
Dynamic link
Each stack frame contains a reference to the method to which the stack frame belongs in the runtime constant pool, which is held to support dynamic connections during method calls. We know that the constant pool of Class files contains a large number of symbolic references, and the method call instructions in the bytecode take the symbolic references that point to the method in the constant pool as parameters. Some of these symbolic references are converted to direct references during the class loading phase or the first time they are used, which is called static parsing. The other part is converted to a direct reference during each run, which is called a dynamic connection.
Characteristics of virtual machine stack
Thread private
The life cycle is the same as the thread
Exception of virtual machine stack
One is StackOverflowError.
The current thread throws this exception if the requested stack depth is greater than the depth allowed by the virtual machine. For example, recurring a function repeatedly to yourself will eventually result in a stack overflow error (StackOverflowError).
The code listing is as follows:
Public class StackOverflowErrorDemo {public static void main (String [] args) {printStackOverflowError ();} public static void printStackOverflowError () {printStackOverflowError ();}}
Output exception result:
Exception in thread "main" java.lang.StackOverflowError stack length:9482 at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech. Jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22) at com.itech.jvm.demo.StackOverflowErrorDemo.printStackOverflowError (StackOverflowErrorDemo.java:22)
It should be noted that in a single thread environment, regardless of whether the stack frame is too large or the virtual machine stack capacity is too small, the virtual machine will throw a StackOverflowError exception when memory cannot be allocated.
One is OOM exception.
When the virtual machine stack supports dynamic extension, an OOM exception is thrown if enough memory cannot be applied for.
The code listing is as follows:
Public class VMOOMDemo {public static void main (String [] args) throws Throwable {VMOOMDemo demo = new VMOOMDemo (); demo.printVMOOM ();} public void printVMOOM () {while (true) {new Thread () {public void run () {while (true) {}. Start ();}
This example is used with caution.
This example generates a memory overflow exception by constantly building threads. However, the resulting memory overflow exception has nothing to do with whether the stack space is large enough, or precisely, in this case, the larger the memory allocated to each thread's stack, the more likely it is to produce a memory overflow exception. The reason is that the memory allocated by the operating system to each process is limited, for example, the 32-bit Windows is limited to 2 GB.
The function of virtual machine stack
Used to store local variables, operation stacks, dynamic links, method exits
Application of virtual machine stack
For 32-bit jvm, the default size is 256 kb, while for 64-bit jvm, the default size is 512 kb, and the maximum value of the virtual machine stack can be set with-Xss. However, if the setting is too large, it will affect the number of threads that can be created.
Local method stack (Native Method Stack)
The concept of local method stack
The role of the local method stack is similar to that of the virtual machine stack, except that the virtual machine stack serves to execute Java code methods, while the local method stack serves Native methods. Like the virtual machine stack, the local method stack throws StackOverflowError and OutOfMemoryError exceptions.
Characteristics of local method stack
Thread private
Serving the Native method
Exceptions to the local method stack
Like the virtual machine stack, the local method stack throws StackOverflowError and OutOfMemoryError exceptions.
The role of the local method stack
Diplomatic interaction with java environment
Sometimes java applications need to interact with the environment outside the java. This is the main reason for the existence of local methods, and you can think about what happens when java needs to exchange information with some underlying system, such as the operating system or some hardware.
The local approach is such a communication mechanism: it provides us with a very concise interface, and we don't need to know the tedious details outside of java applications.
Interact with the operating system
JVM supports the java language itself and the runtime library. It is the platform on which java programs live. It consists of an interpreter (interpreting bytecode) and libraries connected to native code. However, it is not a complete system after all, and it often depends on the support of some underlying systems (underneath below). These underlying systems are often powerful operating systems. By using native methods, we are able to use java to interact with the underlying system of jre, and even some parts of JVM are written in C, and if we want to use some features of the operating system that are not encapsulated by the java language itself, we also need to use native methods.
Sun's Java Sun's interpreter is implemented in C, which allows it to interact with the outside world like some ordinary C. Jre is mostly implemented in java, and it also interacts with the outside world through some native methods. For example: class java.lang.Thread
The setPriority () method is implemented in java, but it implements a call to the local method setPriority0 () in the class. This native method is implemented in C and is embedded inside JVM, and on Windows 95 platforms, this native method will eventually call Win32 SetPriority () API. This is a concrete implementation of a local method provided directly by JVM, and more often provided by an external dynamic link library (external dynamic link library) and then called by JVM.
4. Java heap (Heap)
The concept of Java heap
The Java heap is arguably the largest piece of memory in a virtual machine. It is the memory area shared by all threads, and almost all instance objects are stored in this area. Of course, with the development of the JIT compiler, the allocation of all objects on the heap has gradually become less "absolute".
The Java heap is the main area managed by the garbage collector. Since today's collectors basically use generation-by-generation collection algorithms, all Java heaps can be subdivided into the new generation and the old generation. In detail, the new generation is divided into:
Eden space
From Survivor
To Survivor
According to the Java virtual machine specification:
The Java heap can be in physically discontiguous memory space as long as it is logically contiguous, just like our disk space. In the implementation, it can be either fixed size or extensible, but the current mainstream virtual machines are implemented according to extensibility.
Characteristics of Java reactor
Shared area between threads, created when the virtual machine starts
Is the largest piece of memory in the virtual machine, and almost all instance objects are stored in this area
Exception of Java heap
An OutOfMemoryError exception is thrown when the heap can no longer be extended.
The role of Java heap
The only purpose is to store object instances, and almost all object instances allocate memory in the java heap
Application of Java reactor
Controlled by-Xmx and-Xms
Program Calculator (Program Counter Register)
The concept of Program Calculator
Similar to PC registers, program counters are private areas of threads, and each thread has its own program calculator. Think of it as a line number indicator of the bytecode executed by the current thread.
The characteristics of program calculator
Thread private
Take up a small amount of memory
This memory region is the only one that does not specify any OOM (OutOfMemoryError) conditions in the Java virtual machine specification.
The exception of a program calculator
This memory region is the only one that does not specify any OOM (OutOfMemoryError) conditions in the Java virtual machine specification.
The function of program calculator
Signal indicator: when switching between multithreads, you need to restore the current execution position of each thread and find the bytecode of the instruction to be executed through the values in the program counter
If the thread is executing the Java method, the counter records the address of the virtual machine bytecode instruction that is executing; if the Native method is executed, the value of the counter is Undefined.
Application of Program Calculator
Controlled by-Xmx and-Xms
VI. Direct memory (Direct Memory)
What is direct memory and indirect memory?
According to the official document:
A byte buffer is either direct or non-direct. Given a direct byte buffer, the Java virtual machine will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer's content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system's native O operations.
Byte byffer can be of two types, one based on direct memory (that is, non-heap memory) and the other based on indirect memory (that is, heap memory).
Direct memory (Direct Memory) is neither part of the run-time data area of the virtual machine nor the memory area defined in the Java virtual machine specification, but this part of memory is used frequently and may also lead to OutOfMemoryError exceptions.
For direct memory, JVM will have higher performance on IO operations because it directly acts on IO operations on the local system. If the heap memory is to be IO operated, it will be copied to direct memory first, and then processed with local IO.
From the perspective of data flow, the chain of action of indirect memory:
Local IO-- > Direct memory-> indirect memory-> Direct memory-> Local IO
The chain of action of direct memory:
Local IO-- > Direct memory-> Local IO
Obviously, direct memory is more efficient when doing IO processing, such as when sending large amounts of data over the network.
A direct byte buffer may be created by invoking the allocateDirect factory method of this class. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers. The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint (memory usage) of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system's native I/O operations. In general it is best to allocate direct buffers only when they yield a measureable gain in program performance.
But because direct memory is created using allocateDirect, it costs more performance than applying for normal heap memory. However, it does not take up the heap memory of the application. So, when you have a lot of data to cache, and its life cycle is longer, then using direct memory is a good choice. However, if this choice does not result in a significant performance improvement, heap memory is recommended.
In JDK1.4 's NIO, one method for ByteBuffer is:
Public static ByteBuffer allocateDirect (int capacity) {return new DirectByteBuffer (capacity);} DirectByteBuffer (int cap) {. Protected static final Unsafe unsafe = Bits.unsafe (); unsafe.allocateMemory (size);. } public final class Unsafe {. Public native long allocateMemory (long var1); }
In addition, it is directly limited by the size of the local total memory (including RAM and SWAP areas or paging files) and the processor addressing space.
When configuring virtual machine parameters, the server administrator will generally configure the virtual machine parameters according to the actual memory settings-Xmx and other parameter information, but often ignore the direct memory, so that the sum of each memory area is greater than the physical memory limit (including physical and operating system-level limits), resulting in OutOfMemoryError exceptions during dynamic expansion.
Characteristics of direct memory
Not limited by Java heap size
Neither part of the runtime data area of the virtual machine, nor the memory area defined in the Java virtual machine specification, will not occupy the memory of the application
IO operations have higher performance because it directly affects the IO operations of the local system
It costs more performance than applying for normal heap memory.
Exception of direct memory
OutOfMemoryError exception occurs during dynamic expansion
The role of direct memory
Based on Channel and Buffer, it can use the Native function library to allocate out-of-heap memory directly, and then use 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.
The use of direct memory
XX:MaxDirectMemorySize=10M
The usage scenario of direct memory
For example, in IO processing, such as when the network sends a large amount of data, direct memory will be more efficient.
At this point, I believe you have a deeper understanding of "how to understand and master the Java virtual machine memory area". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
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.