Learning JVM from scratch (5) - the method area of the runtime data area

1. Basic introduction to the method area

Official documentation: The Java® Virtual Machine Specification

The "Java Virtual Machine Specification" clearly states: "Although all method areas are logically part of the heap, some simple implementations may not choose to perform garbage collection or compression." But for HotSpotJVM, the method The area also has an alias called Non-Heap (non-heap), the purpose is to separate it from the heap. soThe method area is regarded as a memory space independent of the Java heap. The runtime data area structure diagram of the JVM is as follows:
insert image description here

Looking at the JVM's memory area from the perspective of thread sharing or not:

insert image description here

The method area is the same as the Java heap, which isThe memory area shared by each thread. The method area is created when the JVM starts, and its actual physical memory space can be discontinuous just like the Java heap area. The size of the method area is the same as the heap space, which can be fixed or expandable. This area of ​​memory is freed when the JVM is shut down.

The size of the method area determines how many classes the system can save. If the system defines too many classes and the method area overflows, the virtual machine will also throw a memory overflow error: (before java.lang.OutOfMemoryError:PermGen spacejdk1.7) or java.lang.OutOfMemoryError:Metaspace(after jdk1.8) .

Initialize an object for an area allocated in JVM memory as follows:
insert image description here

For an object in the JVM, the interaction diagram of the stack, heap, and method area is as follows:
insert image description here

2. The evolution of the method area in Hotspot

Before jdk1.7, it is customary to call the method area the permanent generation. Starting from jdk1.8, the permanent generation is replaced by the metaspace.

In essence, the method area and the permanent generation are not equivalent, only for Hotspot. The "Java Virtual Machine Specification" does not make uniform requirements on how to implement the method area. For example: BEA JRockit/IBM J9 does not have the concept of permanent generation. Looking at it now, it was not a good idea to use the permanent generation back then. This can easily lead to program OOM ( XX:MaxPermSizelimit exceeded)
insert image description here

insert image description here

When Hotspot arrived in JDK8, it finally completely abandoned the concept of permanent generation, and replaced it with the metaspace implemented in local memory like JRockit and J9.

insert image description here

The essence of the metaspace is similar to that of the permanent generation, which is the implementation of the method area in the JVM specification. However, the biggest difference between metaspace and permanent generation is:The metaspace is not in the memory set by the virtual machine, but uses local memory. The permanent generation and metaspace are not only changed in name, but the internal structure is also adjusted. According to the "Java Virtual Machine Specification", if the method area cannot meet the new memory allocation requirements, an OOM exception will be thrown.

3. Set the method area size and OOM solution ideas

3.1 Set the method area size

The size of the method area is not fixed, and the JVM can be dynamically adjusted according to the needs of the application.

jdk7 and before
use to -XX:PermSizeset the permanent generation initial allocation space. The default value is 20.75M, which is used to -XX:MaxPermSizeset the maximum allocatable space of the permanent generation. 32-bit machine default is 64M, 64-bit machine mode is 82M. When the class information capacity loaded by the JVM exceeds this value, an exception will be reported OutOfMemoryError:PermGen space.

jdk8 and later

  • The metadata area size can be specified using parameters -XX:MetaspaceSizeand-XX:MaxMetaspaceSize
  • The default is platform dependent. Under Windows, -XX:MetaspaceSize=21M -XX:MaxMetaspaceSize=-1// there is no limit.
  • Unlike the permanent generation, if you do not specify a size, the virtual machine will by default use up all available system memory. If the metadata area overflows, the virtual machine will also throw an exceptionOutOfMemoryError:Metaspace
  • -XX:MetaspaceSize: Set the initial metaspace size. For a 64-bit server-side JVM, the default -XX:MetaspaceSizevalue is 21MB. This is the initial high water mark, once this water mark is hit, Full GC will be triggered and unload useless classes (that is, the class loaders corresponding to these classes are no longer alive), and then the high water mark will be reset. The value of the new high-water mark depends on how much metaspace is freed after GC. If the freed space is insufficient, MaxMetaspaceSizeincrease the value appropriately if it does not exceed. If there is too much space to be freed, reduce this value appropriately.
  • If the initial high-water mark is set too low, the high-water mark adjustment described above can occur many times. Through the log of the garbage collector, it can be observed that the Full GC is called multiple times. In order to avoid frequent GC, it is recommended to -XX:MetaspaceSizeset it to a relatively high value.

3.2 How to solve OOM

  1. For OOM exceptions or heap space exceptions, the general method is to first analyze the dumped heap dump snapshots through a memory image analysis tool (such as Eclipse Memory Analyzer). The key point is to confirm whether the objects in the memory are necessary, that is, to First distinguish whether there is a memory leak (Memory Leak) or a memory overflow (Memory Overflow)
  2. If it is a memory leak, you can further use the tool to view the reference chain from the leaked object to GC Roots. Then you can find out how the leaked objects are associated with GCRoots and prevent the garbage collector from reclaiming them automatically. After mastering the type information of the leaked object and the information of the GCRoots reference chain, the location of the leaked code can be located more accurately.
  3. If there is no memory leak, in other words, the objects in the memory must still be alive, then you should check the heap parameters (-Xmx and -Xms) of the virtual machine, and compare them with the physical memory of the machine to see if they can be increased. From the code, check whether there are some objects whose life cycle is too long and the holding state time is too long, and try to reduce the memory consumption of the program during runtime.

4. Internal structure of the method area

The book "In-depth Understanding of the Java Virtual Machine" describes the storage content of the method area as follows:

It is used to store type information loaded by the virtual machine, constants, static variables, code cache compiled by a Just-In-Time Compiler (Just-In-Time Compiler, just-in-time compiler), etc.

insert image description here

(1) Type information
For each loaded type (class class, interface interface, enumeration enum, annotation annotation), the JVM must store the following type information in the method area:

  1. The full valid name of this type (fullname = packagename.classname)
  2. The fully qualified name of the immediate superclass of this type (for interface or java.lang.object, there is no superclass)
  3. Modifiers of this type (public, abstract, some subset of final)
  4. an ordered list of the direct interfaces of this type

(2) Field (Field) information
The JVM must save the relevant information of all fields of the type and the declaration order of the fields in the method area.

Domain related information includes: domain name, domain type, domain modifier (a subset of public, private, protected, static, final, volatile, transient)

(3) Method (Method) information
JVM must save the following information of all methods, including the order of declaration as domain information:

  1. method name
  2. The method's return type (or void)
  3. Number and types of method parameters (in order)
  4. Method modifiers (a subset of public, private, protected, static, final, synchronized, native, abstract)
  5. Method bytecodes (bytecodes), operand stack, local variable table and size (except for abstract and native methods)
  6. Exception table (except abstract and native methods) The start position and end position of each exception processing, the offset address of the code processing in the program counter, the constant pool index of the caught exception class

(4) Non-final class information

  • Static variables are associated with the class, loaded as the class is loaded, and they become a logical part of the class data
  • A class variable is shared by all instances of the class, and you can access it even when there is no instance of the class
public class MethodAreaTest {
    
    
    public static void main(String[] args) {
    
    
        Order order = new Order();
        order.hello();
        System.out.println(order.count);
    }
}
class Order {
    
    
    public static int count = 1;
    public static void hello() {
    
    
        System.out.println("hello!");
    }
}

(5) Global constants (static final)

Class variables declared final are handled differently, and each global constant is assigned at compile time.

5. Runtime constant pool

Official documentation: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

The method area contains a runtime constant pool, and the bytecode file contains a constant pool. To figure out the runtime constant pool in the method area, you need to understand the constant pool in the bytecode file.
insert image description here

5.1 Constant pool

insert image description here
In addition to descriptor information such as class version information, fields, methods, and interfaces, an effective bytecode file also contains a piece of information that is the constant pool table (Constant Pool Table), including various literals and pairs of types, Symbolic references to fields and methods

Why do you need a constant pool?

Classes and interfaces in a java source file are compiled to generate a bytecode file. The bytecode in Java needs data support. Usually this kind of data is too large to be directly stored in the bytecode. In another way, it can be stored in the constant pool. This bytecode contains pointers to the constant pool. references. The runtime constant pool is used during dynamic linking, which was introduced earlier.
For example, the following code:

public class SimpleClass {
    
    
    public void sayHello() {
    
    
        System.out.println("hello");
    }
}

Although it is only 194 bytes, structures such as String, System, PrintStream, and Object are used in it. The amount of code here is actually very small. If there is more code, there will be more referenced structures, so a constant pool is needed here.
insert image description here

The data types stored in the constant pool include:

  • quantity value
  • string value
  • class reference
  • field reference
  • method reference

insert image description here
Summarize:The constant pool can be regarded as a table, and the virtual machine instruction finds the class name, method name, parameter type, literal value and other types to be executed according to this constant table

5.2 Introduction to runtime constant pool

  • The Runtime Constant Pool is part of the method area.
  • The constant pool table (Constant Pool Table) is part of the Class file,Used to store various literals and symbol references generated during compilation, which will be stored in the runtime constant pool in the method area after the class is loaded
  • Runtime constant pool, after loading classes and interfaces to the virtual machine, the corresponding runtime constant pool will be created.
  • The JVM maintains a constant pool for each loaded type (class or interface). Data items in a pool, like array items, are accessed by index.
  • The runtime constant pool contains a variety of different constants, including numeric literals that have been defined at compile time, and method or field references that can only be obtained after runtime parsing. At this time, it is no longer the symbolic address in the constant pool, and it is replaced by the real address here.
  • Another important feature of the runtime constant pool compared to the Class file constant pool is that it is dynamic. (eg String.intern() method)
  • The runtime constant pool is similar to the symbol table in traditional programming languages, but it contains more data than the symbol table.
  • When creating a runtime constant pool of a class or interface, if the memory space required to construct the runtime constant pool exceeds the maximum value that the method area can provide, the JVM will throw an exception OutOfMemoryError.

6. Example of using the method area

public class MethodAreaDemo {
    
    
    public static void main(String args[]) {
    
    
        int x = 500;
        int y = 100;
        int a = x / y;
        int b = 50;
        System.out.println(a+b);
    }
}

Decompile the bytecode file into a txt file

javap -v -p MethodAreaDemo01.class > test01.txt

insert image description here
insert image description here
insert image description here

insert image description here

insert image description here

insert image description here

insert image description here
insert image description here

insert image description here
insert image description here
insert image description here

insert image description here

insert image description here

insert image description here
insert image description here

insert image description here

7. Details of the evolution of the method area

First of all, it is clear that only HotSpot has permanent generation. For BEA JRockit, IBM J9, etc., there is no concept of permanent generation. In principle, how to implement the method area belongs to the implementation details of the virtual machine, and is not subject to the "Java Virtual Machine Specification", and does not require uniformity. Changes in the method area in Hotspot:

insert image description here

insert image description here

insert image description here

insert image description here

7.1 Why should the permanent generation be replaced by metaspace

With the arrival of Java8, the permanent generation is no longer seen in the HotSpot VM. But this does not mean that the metadata information of the class has disappeared. These data are moved to a local memory area that is not connected to the heap, this area is called metaspace (Metaspace).

Since the metadata of the class is allocated in the local memory, the maximum allocatable space of the metaspace is the available memory space of the system. This change is necessary for the following reasons:

● It is difficult to determine the size of the permanent generation space. In some scenarios, if there are too many dynamically loaded classes, it is easy to generate oom in the Perm area. For example, in an actual web project, because there are many function points, many classes must be dynamically loaded during operation, and fatal errors often occur.

"Exception in thread 'dubbo client x.x connector' java.lang.OutOfMemoryError:PermGen space"

The biggest difference between the metaspace and the permanent generation is that the metaspace is not in the virtual machine, but uses local memory. So by default the size of the metaspace is limited only by local memory.
● It is difficult to tune the permanent generation.

7.2 Why does StringTable need to adjust its position

StringTable is placed in the heap space in jdk7. Because the recycling efficiency of the permanent generation is very low, it will only be triggered during full gc. The full gc is only triggered when there is insufficient space in the old generation and the permanent generation is insufficient. This leads to inefficient recycling of StringTable. In our development, a large number of strings will be created, and the recycling efficiency is low, resulting in insufficient memory in the permanent generation. Putting it in the heap can reclaim memory in time.

7.3 Where are static variables stored?

From the conceptual model defined in the "Java Virtual Machine Specification", all Class-related information should be stored in the method area, but the "Java Virtual Machine Specification" does not stipulate how to implement the method area, which is It has become a thing that allows different virtual machines to be flexibly controlled by themselves. The HotSpot virtual machine of JDK7 and later versions chooses to store the static variable and the mapping class object of the type at the Java language side together, and store it in the Java heap.

8. Garbage collection in the method area

Some people think that the method area (such as the metaspace or permanent generation in the Hotspot virtual machine) has no garbage collection behavior, but it is not. The "Java Virtual Machine Specification" has very loose constraints on the method area. It has been mentioned that the virtual machine may not be required to implement garbage collection in the method area. In fact, there are indeed collectors that do not implement or fail to fully implement type unloading in the method area (for example, the ZGC collector in the JDK 11 period does not support class unloading).

Generally speakingThe recovery effect in this area is relatively difficult to be satisfactory, especially the type of unloading, the conditions are quite harsh. But the recycling of this part of thesometimes it is necessaryof. In the previous bug list of sun company, several serious bugs appeared because the low version of the HotSpot virtual machine did not fully reclaim this area, resulting in memory leaks

Garbage collection in the method area mainly recycles two parts:Obsolete constants and unused types in the constant pool

There are two main types of constants stored in the constant pool in the method area: literals and symbolic references. Literal quantities are closer to the constant concept at the Java language level, such as text strings, constant values ​​declared as final, and so on. Symbolic references belong to the concept of compilation principles, including the following three types of constants:

  1. fully qualified names of classes and interfaces
  2. Field names and descriptors
  3. method name and descriptor

The recovery strategy of the Hotspot virtual machine for the constant pool is very clear.As long as the constants in the constant pool are not referenced anywhere, they can be recycled.Recycling obsolete constants is very similar to reclaiming objects in the Java heap.

It is relatively simple to determine whether a constant is "obsolete", but it is more stringent to determine whether a type belongs to a "class that is no longer used". The following three conditions need to be met at the same time:

● All instances of this class have been recycled, that is, there are no instances of this class and any derived subclasses in the Java heap.
● The class loader that loads this class has been recycled. This condition is usually difficult to achieve unless it is a well-designed scenario where the class loader can be replaced, such as OSGi and JSP reloading.
● The java.lang.Class object corresponding to this class is not referenced anywhere, and the methods of this class cannot be accessed through reflection anywhere.

The Java virtual machine is allowed to recycle useless classes that meet the above three conditions. What I mean here is only "allowed", not the same as objects, which will inevitably be recycled if they are not referenced. Regarding whether to recycle the type , the HotSpot virtual machine provides -Xnoclassgcparameters to control, and you can also use -verbose:classand to view class loading and unloading information-XX:+TraceClassLoading-XX:+TraceClassUnLoading

In scenarios where reflection, dynamic proxies, CGLib and other bytecode frameworks are used extensively, and frequent custom class loaders such as JSP and OSGi are dynamically generated, the Java virtual machine is usually required to have the ability to unload types to ensure that methods will not be region causing excessive memory pressure.

Summary diagram of the runtime data area:
insert image description here

The notes are summarized from the video tutorial: Shang Silicon Valley Song Hongkang JVM full set of tutorials (detailed java virtual machine)
reference:
1. "In-depth understanding of Java virtual machine" 2nd edition

Guess you like

Origin blog.csdn.net/huangjhai/article/details/120623151