I. Linux and Process memory models
The JVM is the identity of a process running on a Linux system, and understanding the memory relationships of Linux and processes is the basis for understanding the relationship between JVM and Linux memory.
Overview relationships between hardware, system, and process three levels of memory
1, from the hardware, the Linux system has two parts: physical memory and Swap (on disk), physical memory is the main memory area used by Linux activities, when the physical memory is not enough to use, Linux will be part of the temporarily unused memory data in the swap, To free up more free memory space, and when you need to use data that is in swap, you must first swap it back in memory.
2, from the Linux system, in addition to the boot system bin area, the entire memory space is divided into two parts: kernel memory (Kernel space), user memory (users space).
Kernel memory is the memory space used by Linux itself, which is mainly used for program logic, such as program scheduling, memory allocation, connection hardware resources, and so on. User memory is the main space for each process, and Linux provides the same virtual memory space for each process, which makes the processes independent and non-intrusive. The implementation of the method is the use of virtual memory technology: to allocate a certain amount of virtual memory for each process, if the virtual memory is used up, the allocation of physical memory, for 32 of the Linux system, the general 0~3g virtual memory space allocation as a user space, the 3~4G virtual memory space allocated to the kernel space The division of the 64-bit system is similar.
3, from the process point of view, the process can directly access the user memory (virtual memory space) is divided into 5 parts: Code area, data area, heap area, stack area, unused area.
The code area primarily holds the machine code of the application, and the code cannot be modified during operation, with a read-only and fixed-size feature.
The data area holds the global data, static data, and some constant strings in the application, and the area is also fixed.
A heap is a space for a dynamic application of a runtime program, which is a memory resource that is requested and freed directly while the program is running.
The stack area is used to store data such as incoming parameters, temporary variables, and return addresses of functions.
Unused extents are prestaged areas that allocate new memory space.
Second, process and JVM memory models
The JVM is essentially a process, so its memory model also has the general characteristics of the process. However, the JVM is not a normal process, it has many new features in the memory model, the main reason is two: 1. The JVM has migrated many of the things that would otherwise be part of the operating system management into the JVM, with the aim of reducing the number of system calls; 2. Java NIO, which is designed to reduce the overhead of system calls for read and write Io, and the JVM process is compared to the normal process memory model:
1. User memory
It is emphasized that the code area and data area of the JVM process model refer to the JVM itself, not the Java program. The normal process stack area is generally used only as a line stacks in the JVM. The difference between the JVM's heap area and the normal process is the largest, as detailed below:
The first is the permanent generation. The permanent generation is essentially the code area and data area of the Java program. Classes in Java programs are loaded into different data structures throughout the region, including constant pools, fields, method data, method bodies, constructors, and specialized methods in classes, instance initialization, interface initialization, and so on. This area is a part of the heap for the operating system, and for Java programs It is a space for the program itself and for static resources, allowing the JVM to interpret the execution of Java programs.
Next is the new generation and the old age. The new generation and the old era are the real heap space used by Java programs, mainly for memory object storage, but its management and ordinary processes are fundamentally different.
When a normal process allocates space to a memory object at run time, such as when C + + performs a new operation, it triggers a system call that allocates memory space, which is returned when the thread of the operating system allocates space based on the size of the object, and when the program releases the object, such as C + + when the delete operation is performed. A system call is also triggered to notify the operating system that the space occupied by the object is already recyclable.
The JVM uses the memory differently from the general process. The JVM applies an entire memory area to the operating system (the specific size can be adjusted in JVM parameters) as a heap of Java programs (divided into the Cenozoic and the old); When a Java program requests memory space, such as a new operation, the JVM allocates the required size to the Java program in that space. And the Java program is not responsible for notifying the JVM when it can free up space for this object, and the garbage object's memory space is reclaimed by the JVM.
The advantages of the JVM's memory management approach are obvious, including: first, to reduce the number of system calls, the JVM does not require operating system intervention to allocate memory space to Java programs, and only needs to request memory or notification collection to the operating system when the Java heap size changes. and the normal program every time the allocation of memory space will require system calls to participate; second, to reduce memory leaks, the normal program does not (or not in time) notify the operating system memory space release is one of the important reasons for memory leaks, and by the JVM Unified management, you can avoid the memory leakage problem of programmers.
The last is the unused area, which is the prestaged area for allocating new memory space. For normal processes, this area can be used for heap and stack space application and release, each heap memory allocation will use this area, so the size changes frequently, for the JVM process, the size of the heap and line stacks to use the region, and the heap size is generally less adjustment, so the size is relatively stable. The operating system dynamically adjusts the size of the area, and the area is not usually allocated actual physical memory, only allowing the process to apply for heap or stack space in this area.
2. Kernel memory
Applications typically do not deal directly with kernel memory, kernel memory is managed and used by the operating system, but with Linux's performance concerns and improvements, some new features allow applications to use kernel memory or to map to kernel space. The Java NiO is born in this context, which takes full advantage of the new features of the Linux system and improves the IO performance of Java programs.
The distribution of Linux systems in the kernel used by Java NiO is given. NIO buffer mainly includes: NiO uses a variety of channel when using the Bytebuffer, Java program actively use the Bytebuffer.allocatedirector request allocated buffer. In Pagecache, the memory used by NiO mainly includes: Filechannel.map mode to open the file occupies mapped, The cache required by Filechannel.transferto and Filechannel.transferfrom (NIO file is shown in the figure).
The use of NIO buffer and mapped can be monitored by jmx, as shown in. However, the implementation of FileChannel is using native Pagecache through system calls, and the process is transparent to Java and cannot monitor the size of this portion of memory usage.
Linux and Java NiO make room for program use in kernel memory, mainly to reduce the duplication, to reduce the overhead of IO operating system calls. For example, to send data from a disk file to a NIC, using the normal method and NIO, the data flow comparison is shown:
Copying data between kernel memory and user memory is more resource-intensive and time-consuming, and as we can see, it reduces the copy of data between kernel memory and user memory by NiO by 2 times. This is one of the important mechanisms for high performance of Java NiO (the other is asynchronous non-blocking).
As can be seen from the above, kernel memory is also very important for Java program performance, so when dividing the system memory usage, make sure to set aside some free space for the kernel.
Linux and Process memory models