First, class loading subsystem

Is responsible for loading class information from the file system or network. The loaded class information is stored in a memory space called the method area.

2. Method area

The method area is just a specification defined in the JVM specification and needs to be implemented by each JVM vendor. In contrast to HotSpot, it is the so-called permanent generation or the meta space after JDK8. Like the Java heap, it is a memory area shared by all threads. The method area stores class information, constants, static variables, code compiled by the real-time compiler, and data that have been loaded by the virtual machine. Its size determines how many classes the system can hold.

There are a number of changes made between JDK6,7 and 8 for Hotspot virtual machines:

Before JDK7

Before JDK7, it can be understood as Perm, and the size can be specified by -xx :PermSize and -xx :MaxPerSize. Symbols, pools of string constants, class static variables, run-time pools of constants, and other information all exist in this area, which is isolated from heap logic and shares a contiguously large space of memory

JDK7

The permanent generation was removed from JDK1.7, but not completely. It simply moves string constants from the permanent generation, the class’s static variable pool to the Java Heap, and symbolic references to Native Memory

JDK8

After JDK8, the permanent extentis removed completely, replaced by MetaSpace and some miscellaneous items that previously existed in the permanent generation are moved to the heap.

Similar to Oracle JRockit and IBM JVMS, space is allocated in local memory, a chunk of direct memory outside the heap. If you do not specify the size, the default VM will use up all available system memory. You can specify the size by running the -xx :MaxMetaSpaceSize command.

The reason for the transformation of a permanent generation into a meta-space

Because the size of the permanent generation is not easy to determine, so the string constant pool in the permanent generation is prone to memory overflow,JRockit does not have the concept of permanent generation, but also to be consistent with JRockit for easy merge, etc. More reference: mail.openjdk.java.net/pipermail/h…

www.oracle.com/webfolder/t…

Three, heap

The Java heap is created at virtual machine startup and is the primary memory working area for Java programs. The heap is the run-time data area from which almost all the memory for class instances and arrays is allocated. Heap space, an area of memory closely associated with Java applications, is shared by all threads.

The heap is divided into young generation and old generation. The young generation stores newly created objects (which have a short lifetime), while the old generation stores larger objects that are not easily destroyed.

Direct memory

Direct memory is an area of memory outside the Java heap that is directly requested from the system. Direct memory is often accessed faster than the Java heap. Therefore, you may consider using direct memory in read-write situations. Since direct memory exists outside the Java heap, its size is not directly limited by the maximum heap size specified by Xmx, but system memory is limited. Java’s NIO libraries allow Java programs to use direct memory.

Five, garbage collection system

The garbage collection system is an important part of the Java virtual Machine. The garbage collector can reclaim the method area, the Java heap, and direct memory.

Vi. Vm stack

Each virtual machine thread has a private Java stack. The Java virtual machine stack is created when the thread is created. The stack holds the stack frame information, local variables, method parameters and so on. When executed, each method creates a stack frame and merges it into the stack. The stack frame stores information such as the local variable table, operand stack, dynamic link, and return address. Conversely, when a method call ends and returns, the corresponding stack frame is also out of the stack.

StackOverflowError and OutOfMemoryError can occur in this area

In the HotSpot virtual machine, the stack size can be specified by ** -xSS **, and the stack size also determines the depth of reachability of function calls.

6.1 Local variation table

The local variable table is one of the important parts of the stack frame, and it is the local variable table that is most closely related to the performance tuning in the stack frame. The local variable table is used to hold the parameters and local variables of the method. For nonstatic methods, the virtual machine also passes the current corresponding reference as an incoming parameter to the method to be executed.

The local variable table is a set of binary strings numbered in words (**) that occupy a separate memory unit in computer memory. Generally, a word on a 32-bit machine is 4 bytes in length). A word has 32 bits, so for long and double types, we need to use two “words” for storage. The “word” space can be reused. For example, if two variables a and b are defined in a method,b will occupy the same word space as A if a is no longer in scope when b is defined. Here is an example:

The first step is to install a JClassLib plug-in in our IDEA. There is a metric in the method called “Maximum local variables”, which indicates the Maximum capacity (in words) of local variables in the stack frame when the method is executed. Look at the following method

    private void  test(){
        int a;
        int b;
    }
Copy the code

The method defines two local variables, a and b, and they are of the same scope. See “Maximum local variables” through jclasslib.You can see that the number displayed here is 3, because in addition to the two local variables we defined, there is also a reference to this to the current object.

Next, change the code a little:

    private void  test(){
        {
            int a;
        }
        int b;
    }
Copy the code

Again, look through Jclasslib to see the maximum required capacity of the local variable table

Variables in the local variable table are also important garbage collection root nodes. Objects referenced directly or briefly in the local variable table are not reclaimed. Here are some typical examples:

Public static void test1() {// Apply for 6M space. {byte[] bytes = new byte[6 * 1024 * 1024]; } system.out.println ("test1 starts garbage collection "); System.gc(); System.out.println("test1 ends garbage collection "); } public static void test2() {// Apply for 6M space. {byte[] bytes = new byte[6 * 1024 * 1024]; } int c = 10; System.out.println("test2 begins garbage collection "); System.gc(); System.out.println("test2 ends garbage collection "); }Copy the code

The test1 and test2 functions in the above program both claim 6M of heap space and use local variables to reference this space. Garbage collection is then done through system.gc (). By executing with the JVM argument -xx +PrintGC, we can get the result:

Test1 Start garbage collection [GC (system.gc ()) 8765K->6992K(123904K), 0.0081964 secs] [Full GC (system.gc ()) 6992K->6793K(123904K), 0.0117884 secs] test1 End garbage collection test2 Start garbage collection [GC (system.gc ()) 14248K->6921K(123904K), 0.0017406 secs] [Full GC (system.gc ()) 6921K->626K(123904K), 0.0091824 secs] test2 End garbage collectionCopy the code

The result shows that the heap space of test1 does not change significantly after FullGC occurs, so the 6M of the heap space applied by this byte array is not reclaimed, while the heap space of Test2 changes from 6921 to 626 after GC occurs, about 6M of the heap space is reclaimed. It is known that the 6M space applied in Test2 has been reclaimed by the JVM. So why?

In test1, the local variable bytes is disabled before garbage collection. Bytes is out of scope, but bytes still exists in the local variable table and still refers to a byte array of 6M space, so the byte array still cannot be collected.

In Test2, after the failure of the local variable bytes, a new variable C is defined. At this time, the variable A will reuse the slots (words) of the invalid variable bytes in the local variable table. Therefore, the variable bytes will be destroyed.

6.2 Operand Stack

The operand stack is mainly used to store the intermediate results of the calculation process, and also serves as temporary storage space for variables during the calculation process.

6.3 Frame data area

In addition to local variable tables and operand stacks, Java stack frames also need some data to support constant pool resolution, normal method return, exception handling, and so on. Most Java bytecode instructions require constant pool access. A pointer to the constant pool is stored in the frame data area to facilitate program access to the constant pool.

For exception handling, the JVM needs an exception handling table to find the code that handles the exception when an exception occurs, so the exception handling table is also an important part of the frame data area. The following table shows typical exception handling

Exception table:
from to target type
  4  16  19     any
Copy the code

The preceding exception processing table may throw any exception at bytecode offsets of 4 to 16 bytes. If an exception is encountered, the execution is performed at bytecode offsets of 19. When a method throws an exception, the JVM looks for a similar exception table for processing. If it cannot find a suitable method in the exception table, it terminates the current function call, returns the calling function, and throws the same exception in the calling function.

6.4 Allocation on the stack

Allocation on the stack is an optimization technique provided by the JVM. Basic idea: Objects that are thread private (that is, objects that cannot be accessed by other threads) can be split up and allocated on the stack rather than on the heap. The advantage of allocating on the stack is that it can be self-destruct at the end of the function call, without the intervention of the garbage collector, thus improving system performance.

The technical basis of stack allocation is escape analysis. The purpose of escape analysis is to determine whether an object’s scope is likely to escape from the function body.

Related JVM parameters: -xx :+DoEscapeAnalysis enables escape analysis (you can only use in server mode) -xx +EliminateAllocations opens scalar substitution (default), allowing object allocations to be split on the stack.

For a large number of scattered small objects, allocation on the stack provides a good object allocation optimization strategy, the speed of the stack allocation block, and can effectively avoid the negative impact of garbage collection, but compared with the heap space, the stack space is small, therefore, large objects can not be allocated on the stack is not suitable.

Local method stack

Very similar to the virtual stack, the biggest difference is that the virtual stack is used for Java method calls, while the local method stack is used for local method calls.

Viii. PC register (program counter)

When the number of threads exceeds the number of CPUS, the execution of multiple threads needs to rely on time slice polling to compete for resources, so there needs to be a thread unique space to record where the current thread is executed, this area is called the PC (Program Counter) register. The PC register holds the address of the currently executing JVM instruction.

PC registers are not targeted with native methods

9. Execution engine

One of the most core components of the JVM, responsible for executing the virtual machine’s bytecode.

Appendix: Reference

Dzone.com/articles/ja…

Blog.csdn.net/qq876551724…

www.cnblogs.com/paddix/p/53…

Blog.csdn.net/qq_26222859…