When it comes to the Java Virtual Machine (JVM), most of us Java programmers are probably intimidated by the idea that the JVM is a great way to write Java programs once and run them anywhere. And because of it we can do only focus on business code implementation, and don’t need to care about memory allocation and recovery, only from these two points can see that the Java virtual machine as we have done many things, but also because it is too much for us to do, so we only need to be single-minded to achieve our demand, For the most part, we don’t care how the bottom layer does it, but because it does so much, we don’t know what’s going on in the coding process, let alone how to fix it, so it’s worth understanding how the Java Virtual machine works for us. In this way, we will not be at a loss when we encounter problems.

First, let’s get an idea of what the JVM is and what it can do. The JVM is defined on Wikipedia as follows:

Java Virtual Machine (JVM), a Virtual Machine capable of running Java Bytecode (bytecode), implemented as a stack structured Machine. Originally developed and implemented by Sun Microsystems, the first implementation version is part of the Java platform, capable of running software programs written in the Java language.

Java virtual machines have their own complete hardware architecture, such as processors, stacks, registers, etc., as well as corresponding instruction systems. The JVM shields platform-specific information, allowing Java programs to run unmodified on multiple platforms by generating object code (bytecode) that runs on the Java VIRTUAL machine.

The virtual machine as a programming language is actually not just dedicated to the Java language, but any language can be compiled and run by the JVM as long as the generated compilation file complies with the JVM’s requirements for loading the compilation file format.

The JVM is a Java program that has been compiled to produce bytecodes that can be run on the JVM. How the bytecodes are run depends on the implementation inside the JVM. So it doesn’t just run Java programs, it can run as long as the compiled files meet the JVM’s requirements.

Let’s start with the runtime data region structure of the JVM, which is a common interview question: What is the runtime data region distribution of the Java VIRTUAL machine? If you are prepared for the interview, I believe you must have seen the interview problem, I remember when I just graduated out to prepare the interview often see this interview question, at a time when the truth may have little concept for Java virtual machine, so it is conceivable that it is rote learning in preparation for the interview can only answer, so that over a period of time will forget, If you are familiar with the Java virtual machine (JVM), you will be able to answer the following question.

The JVM defines various run-time data areas during program execution, including the heap, program counters, stacks, method areas, and run-time constant pools. Some of these data areas are created with JVM startup and destroyed upon JVM exit. Some are thread private, initialized at thread creation and destroyed upon thread exit. Each region has a different mission, so here’s a quick look at what each region is responsible for.

The heap

All the class instance and an array of place memory allocation, creating the JVM startup, and all the JVM thread sharing, namely the area class instance and an array of all threads can access, the area size can be fixed, can also according to need elastic extension, the JVM provides launch parameters initialization for programmers to specify the heap size, If elastic, specify the maximum value of the heap. The JVM specifies an initial heap size parameter of -xms and a maximum heap size parameter of -xmx. If you want the heap size to be fixed, just configure the values of -xms and -xmx to be the same, for example, -xMS20m -XMx20m.

Since our program may be creating objects and arrays all the time, and some objects or arrays may not be needed any more after being created once, the garbage collector is needed for memory reclamation. Therefore, the heap area is relatively the focus of the garbage collector. The JVM will throw an OutOfMemoryError when it encounters that the required heap memory is greater than the available memory in this region while allocating memory in this region.

How object instances are allocated in the heap and collected by the garbage collector may require several separate articles, but we’ll leave that to the next article, which will focus on the JVM’s runtime memory distribution.

Program counter

JVM support the execution of multiple threads, each thread has its own program counter, at any time, each thread is currently Method known as the thread of execution of the current Method, if the current Method is not local Method (Native Method), the program counter value is the current thread is executing in the current Method of instruction address, If it is a local method, its value is undefined. In a multithreaded environment, each thread scheduling and execution are allocated by the CPU time, when a thread is allocated time slice after execution needs to be returned to the ready state, waiting for the next scheduled to resume execution, and thread to resume execution can return to the last position to continue execution depends on is the value of the record in the program counter.

The stack

  • The virtual machine stack

    Similarly, each thread also has its own virtual machine stack, which is created with the creation of the thread. It mainly stores the method stack frame generated in the process of method execution. The stack frame contains local variable table, operand stack, dynamic connection, method exit and other information. Each method from call to return corresponds to a stack frame in the virtual machine stack to bounce process.

    In the JVM specification this size can be fixed or extended flexibly as needed. The JVM provides a startup parameter for the programmer to specify the initial size of the virtual stack, or a maximum if it is elastic. A StackOVerflowError will be thrown if the requested stack depth in the thread exceeds the maximum depth allowed by the JVM, or if the JVM stack memory supports dynamic scaling. The JVM throws an OutOfMemoryError when the stack runs out of memory to support the extension during an attempt, or when the thread is created there is not enough memory to initialize the stack for the newly created thread.

    In the case of a HotSpot VIRTUAL machine, it does not support scaling. The size of the stack is determined at the time of creation of the thread initialization. The stack size can be specified with the -xss parameter, for example, -xss20m specifies the stack size of 20MB. Therefore, in the HotSpot virtual machine, there is no OutOfMemoryError caused by stack expansion during the running of the thread. OutOfMemoryError can only be generated when the thread initializing stack memory has been unable to initialize.

  • Local method stack

    Native Method Stacks (or Native Method Stacks) can be made to support Native Method Stacks in Java.

Methods area

Like the heap, it is created at JVM startup and shared by all JVM threads, but it is primarily used to store the structure of each class’s runtime constant pool, type information, constants, static variables, fields, and methods, as well as the just-in-time compiler compiled code cache. The method area is logically part of the heap area, but is sometimes called non-heap to distinguish it from the heap.

The JVM specification is very broad, and the implementation of the method area is up to the specific vm to define. Prior to JDK 8, the HotSpot VIRTUAL machine implemented the method area through persistent generation (permanent generation in garbage collector generation design). In this way, the method area can be managed directly as the garbage collector manages the heap area, eliminating the need to design memory management for the method area. The JVM is more likely to run out of memory if the size of the permanent generation is not set by -xx :MaxPermSize=size, so the implementation of permanent generation is gradually abandoned in the development of JDK. -xx :MaxMetaspaceSize=size Specifies the maximum value of a Metaspace. By default, metaspacesize is not limited by the size of the local memory.

This area is specified in the JVM specification and a simple implementation can choose not to do garbage collection or compression, because this area stores mainly the structural data of the class, and the garbage collector collects the information of the class. For class collection, it requires unloading the class, and the conditions of unloading the class are extremely strict. As a result, the garbage collector does a poor job of collecting in this area, but it is necessary to collect in this area anyway to prevent memory leaks.

Although the JVM specification states that an OutOfMemoryError will be thrown if the memory in the method area cannot continue to satisfy the memory allocation request, since Metaspace has been changed to implement the area through Metaspace since JDK 8, Therefore, outofMemoryErrors are rarely generated in this area, unless local memory is too low to allocate memory for class information generated at runtime.

Run-time constant pool

The runtime constant pool is also mentioned in the method area, which is the part of the method area that stores literal and symbolic references generated during compilation and stored in the area after the class is loaded. Similarly, in the JVM specification, the Java virtual machine will throw an OutOfMemoryError if the memory required for runtime constant pool construction exceeds the memory available in the Java Virtual machine method area when creating a class or interface. But as mentioned above, it is difficult to generate outofMemoryErrors in this region.

Direct memory

Direct memory is not part of the JVM runtime data region, nor is it defined in the JVM specification, but because it is often used, it can cause OutofMemoryErrors. The maximum direct memory that can be used can be set with the -xx :MaxDirectMemorySize=size parameter. In fact, I don’t know much about this part of memory, but I read in the book “Understanding the Java Virtual Machine” that NIO added in JDK 1.4 used this part of memory. This significantly improves performance by avoiding the overhead of copying data back and forth between the Java heap and Native heap using Native methods.

Although this portion of memory is not limited in size like other regions, it is eventually limited by the total memory size of the local machine, so we may only remember to set the heap size parameter and forget about the memory consumption of this portion, resulting in the memory of each region adding up to exceed the total memory size of the local machine. An OutOfMemoryError is generated.

conclusion

Mainly introduced the Java virtual machine on the runtime data areas distribution, and is responsible for the contents of each region, here I strongly recommend zhi-ming zhou with the deep understanding of the Java virtual machine, “the book, the book to each of the above knowledge are very comprehensive analysis, believe that after watching this book you will have a more comprehensive understanding of the JVM. Here to let us through the above content to the Java virtual machine to be able to have a preliminary understanding, then I will extend to each area, and an in-depth understanding, in the process of the thorough understanding further familiar with the Java virtual machine, it can help us to meet a weird question to know how to produce, And then how to solve, but also for our daily coding has a good guiding role, know and know why.

Wechat public number: Rookiedev, Java background development, inspirational lifelong learning, adhere to the output of original dry goods, you can choose to pay attention to me now, or look at the historical article and then pay attention to it. Long press the QR code to pay attention, we work together to become better!