JVM Chapter 9_ Method area

Posted by 86Stang on Fri, 11 Feb 2022 22:36:15 +0100

1. Interaction among stack, heap and method area

The method area is also a very important structure in addition to the heap space
In terms of memory structure, this is the complete structure in a runtime data area

We need to understand how these iterations are allocated to the stack, heap and method area, and how they cooperate

From the perspective of thread sharing or not


Since heap and meta space are shared by threads, their communication is more convenient, but thread safety should be considered, especially in this heap space. Meta space is generally stable except when you load dynamically, so its gc will not be as frequent as heap space.

As for the right side, the error they want to report is StackOverFlow, because they are all the structure of this stack. Program counter, it will not report exceptions, and there is no GC. There is no GC between the virtual machine stack and the local method stack. On the left.

We will use ThreadLocal to ensure the security of multiple threads. This ThreadLocal can be understood separately


The type of Person class is obvious. We will load it into the method area [about the class itself, the. Class file, and the runtime class itself, we need to put it in the method area].

The object of new should be placed in heap space.

If the person = new person () is written in a method, the person is a local variable, and each method is a stack frame. Feel the picture above

2. Understanding of method area

The Java virtual machine specification clearly states: "although all method areas logically belong to a part of the heap, some simple implementations may not choose to garbage collect or compress." However, for the hotspot JVM, there is another alias for the method area called non heap, which is to be separated from the heap.

Therefore, the method area is regarded as a memory space independent of the Java heap.




Metaspace is the landing implementation of the method area, not counting it. So you can understand it as an independent structure

  • The method area of each thread is the same as that of Java heap area. [it means that it is actually a shared area. If this class is not loaded, only one thread can call ClassLoader. If other threads want to use this class, they must wait. That is, we only need to load it once]
  • The method area is created when the JVM starts, and its actual physical memory space can be discontinuous like the Java heap area.
  • The size of the method area is the same as the heap space. You can choose a fixed size or extensible.
  • The size of the method area determines how many classes the system can save. If the system defines too many classes, resulting in overflow of the method area, the virtual machine will also throw a memory overflow error: Java lang.OutofMemoryError:PermGen space
    Or Java lang.OutOfMemoryError:Metaspace
  • Load a large number of third-party jar packages, and there are too many projects deployed by Tomcat (30-50); A large number of dynamically generated reflection classes
  • Closing the JVM frees up memory in this area.

There are many times when we need to load the code, but we can run it.


If the class is loaded too much, that is, it exceeds the size of the method area, it will report OOM. Such as loading a large number of third-party jar packages. Or there are too many projects deployed by Tomcat (30-50). A large number of dynamically generated reflection classes.

Evolution of Hotspot method area

  • In jdk7 and before, it was customary to call the method area permanent generation. Starting with jdk8, the use of meta space replaced the permanent generation. [the method area can be regarded as an interface, and the permanent band or meta space can be regarded as an implementation]

  • In essence, method area and permanent generation are not equivalent. Only for hotspot. The Java virtual machine specification has no unified requirements on how to implement the method area. For example, the concept of permanent generation does not exist in BEA JRockit/IBM J9.

Now, the use of permanent generation was not a good idea. This makes it easier for Java programs to oom (exceeding the upper limit of * * - XX:MaxPermSize * *)

  • In JDK 8, the concept of permanent generation is finally completely abandoned and replaced by Metaspace implemented in local memory like JRockit and J9

  • The essence of meta space is similar to that of permanent generation, which is the implementation of method area in JVM specification. However, the biggest difference between meta space and permanent generation is that meta space is not in the memory set by the virtual machine, but uses local memory.

  • Permanent generation and meta space have not only changed their names, but also adjusted their internal structures.

  • 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. Setting method area size and OOM

  • The size of the method area does not have to be fixed, and the jvm can dynamically adjust it according to the needs of the application.

jdk7 and before:
Set the initial allocation space of the permanent generation through - XX:PermSize. The default value is 20.75M
- XX:MaxPermSize to set the maximum allocable space of the permanent generation. The default of 32-bit machine is 64M, and the mode of 64 bit machine is 82M
When the class information capacity loaded by the JVM exceeds this value, an exception OutofMemoryError:PermGen space will be reported

  • jdk8 and beyond:
  • The size of the metadata area can be specified by the parameter - XX:MetaspaceSize -XX:MaxMetaspaceSize instead of the above two original parameters.

The default value depends on the platform. Under windows, - XX:MetaspaceSize is 21M,
-20: The value of maxmetaspacesize is - 1, which means there is no limit.

Unlike the permanent generation, if the size is not specified, by default, the virtual opportunity exhausts all available system memory. If the metadata area overflows, the virtual machine will throw an exception OutOfMemoryError: Metaspace

 - XX:MetaspaceSize: sets the initial Metaspace size. For a 64 bit server-side JVM, its default
-20: The metaspacesize value is 21MB. This is the initial high water mark. Once this water mark is touched, Full GC will be triggered and useless classes will be unloaded (that is, the class loader corresponding to these classes will no longer survive), and then this high water mark will be reset. The value of the new high watermark depends on how much meta space is released after GC. If the free space is insufficient, increase the value appropriately when it does not exceed MaxMetaspaceSize. If there is too much free space, reduce the value appropriately.

If the initialized high water mark is set too low, the above high water mark adjustment will occur many times. Through the log of the garbage collector, it can be observed that the Full GC is called many times. To avoid frequent GC, it is recommended to set - XX:MetaspaceSize to a relatively high value.

Default value of test setting method area size parameter

/**
 * Default value of test setting method area size parameter
 */
public class MethodAreaDemo {
    public static void main(String[] args) {
        System.out.println("start.........");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end...........");
    }
}


How to solve OOM

1. To solve the 00M exception or heapspace exception, the general method is to first analyze the heap dump snapshot from the dump through the memory image analysis tool (such as Eclipse Memory Analyzer). The focus is to confirm whether the objects in memory are necessary, that is, to distinguish whether there is a memory leak or memory overflow at the end.

2. If it is a memory leak, you can further view the reference chain from the leaked object to GC Roots through the tool. Then we can find out the path through which the leaked objects are associated with GCRoots, which makes it impossible for the garbage collector to collect them automatically. By mastering the type information of the leaked object and the reference chain information of GC Roots, we can accurately locate the location of the leaked code.

3. If there is no memory leak, in other words, the objects in the memory must still exist, you should check the heap parameters (- Xmx and - Xms) of the virtual machine to see if they can be increased compared with the physical memory of the machine, and check whether there are cases where the life cycle of some objects is too long and the holding state time is too long from the code, Try to reduce memory consumption during program run time.

4. Internal structure of method area

In the book "deep understanding of Java virtual machine", the storage content of method area is described as follows:

It is used to store the type information, constants, static variables, code cache compiled by the real-time compiler, etc. that have been loaded by the virtual machine// This is a classic storage form. Different JDK versions are somewhat different. For example, jdk6 static variables exist in the method area, and djk7 and jdk8 static variables exist in the heap space

Domain information and method information are covered in this type of information
Type information

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

① Full and valid name of this type (full name = package name. Class name)
② The full and valid name of the direct parent class of this type (no parent class for interface or java.lang.object)

③ Modifier of this type (a subset of public, abstract and final)
④ This type of direct interface has a sequence table

Field information / member variables / attributes

  • The JVM must store the relevant information of all domains of the type and the declaration order of the domains in the method area.

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

Method information

The JVM must store the following information of all methods, including the declaration order as the domain information:

  • Method name

  • Return type of or void

  • Number and type of method parameters (in order)

  • Modifier of method (a subset of public,private,protected,static,final,synchronized,native,abstract)

  • Bytecodes, operand stack, local variable table and size of method (except abstract and native methods)

  • Exception table (except abstract and native methods)
    The start position and end position of each exception handling, the offset address of the code handler in the program counter, and the constant pool index of the captured exception class

Let's take an example

public class MethadinnecStcuTest extends Object implements Comparable<String>, Serializable {
    // attribute
    public int num = 10;
    private static String str ="Internal structure of test method" ;
    //constructor 
    //method
    public void test1(){
        int count=20;
        System.out.println("count ="+count) ;
    }
    public static int test2(int cal){
        int result=0;
       try {
           int value=30;
           result=value/cal;
       }catch (Exception e){
           e.printStackTrace();
       }
        return result;
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }
}

We decompile through the console instruction javap. Note that javap -v -p is added here to make these modified by private available. And add > test Txt file, which is convenient for us to view

javap -v -p UTF-8 MethadinnecStcuTest.class >MethadinnecStcuTest.
txt

MethadinnecStcuTest.txt as follows

Classfile /E:/bigdataWorkIdea5/project-test/src/main/java/com/bufan/method/MethadinnecStcuTest.class
  Last modified 2021-5-19; size 1350 bytes
  MD5 checksum 61c4d72f3d4f0edb70e3c6355a9a202f
  Compiled from "MethadinnecStcuTest.java"
public class com.bufan.method.MethadinnecStcuTest extends java.lang.Object implements java.lang.Comparable<java.lang.String>, java.io.Serializable
  minor version: 0
  major version: 52
  // Class modifier
  flags: ACC_PUBLIC, ACC_SUPER
// Constant pool
Constant pool:
   #1 = Methodref          #18.#42        // java/lang/Object."<init>":()V
   #2 = Fieldref           #17.#43        // com/bufan/method/MethadinnecStcuTest.num:I
   #3 = Fieldref           #44.#45        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = Class              #46            // java/lang/StringBuilder
   #5 = Methodref          #4.#42         // java/lang/StringBuilder."<init>":()V
   #6 = String             #47            // count =
   #7 = Methodref          #4.#48         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #8 = Methodref          #4.#49         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   #9 = Methodref          #4.#50         // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #10 = Methodref          #51.#52        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #11 = Class              #53            // java/lang/Exception
  #12 = Methodref          #11.#54        // java/lang/Exception.printStackTrace:()V
  #13 = Class              #55            // java/lang/String
  #14 = Methodref          #17.#56        // com/bufan/method/MethadinnecStcuTest.compareTo:(Ljava/lang/String;)I
  #15 = String             #57 / / internal structure of test method
  #16 = Fieldref           #17.#58        // com/bufan/method/MethadinnecStcuTest.str:Ljava/lang/String;
  #17 = Class              #59            // com/bufan/method/MethadinnecStcuTest
  #18 = Class              #60            // java/lang/Object
  #19 = Class              #61            // java/lang/Comparable
  #20 = Class              #62            // java/io/Serializable
  #21 = Utf8               num
  #22 = Utf8               I
  #23 = Utf8               str
  #24 = Utf8               Ljava/lang/String;
  #25 = Utf8               <init>
  #26 = Utf8               ()V
  #27 = Utf8               Code
  #28 = Utf8               LineNumberTable
  #29 = Utf8               test1
  #30 = Utf8               test2
  #31 = Utf8               (I)I
  #32 = Utf8               StackMapTable
  #33 = Class              #53            // java/lang/Exception
  #34 = Utf8               compareTo
  #35 = Utf8               (Ljava/lang/String;)I
  #36 = Utf8               (Ljava/lang/Object;)I
  #37 = Utf8               <clinit>
  #38 = Utf8               Signature
  #39 = Utf8               Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
  #40 = Utf8               SourceFile
  #41 = Utf8               MethadinnecStcuTest.java
  #42 = NameAndType        #25:#26        // "<init>":()V
  #43 = NameAndType        #21:#22        // num:I
  #44 = Class              #63            // java/lang/System
  #45 = NameAndType        #64:#65        // out:Ljava/io/PrintStream;
  #46 = Utf8               java/lang/StringBuilder
  #47 = Utf8               count =
  #48 = NameAndType        #66:#67        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #49 = NameAndType        #66:#68        // append:(I)Ljava/lang/StringBuilder;
  #50 = NameAndType        #69:#70        // toString:()Ljava/lang/String;
  #51 = Class              #71            // java/io/PrintStream
  #52 = NameAndType        #72:#73        // println:(Ljava/lang/String;)V
  #53 = Utf8               java/lang/Exception
  #54 = NameAndType        #74:#26        // printStackTrace:()V
  #55 = Utf8               java/lang/String
  #56 = NameAndType        #34:#35        // compareTo:(Ljava/lang/String;)I
  #57 = internal structure of utf8 test method
  #58 = NameAndType        #23:#24        // str:Ljava/lang/String;
  #59 = Utf8               com/bufan/method/MethadinnecStcuTest
  #60 = Utf8               java/lang/Object
  #61 = Utf8               java/lang/Comparable
  #62 = Utf8               java/io/Serializable
  #63 = Utf8               java/lang/System
  #64 = Utf8               out
  #65 = Utf8               Ljava/io/PrintStream;
  #66 = Utf8               append
  #67 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #68 = Utf8               (I)Ljava/lang/StringBuilder;
  #69 = Utf8               toString
  #70 = Utf8               ()Ljava/lang/String;
  #71 = Utf8               java/io/PrintStream
  #72 = Utf8               println
  #73 = Utf8               (Ljava/lang/String;)V
  #74 = Utf8               printStackTrace
{
// Domain information
  public int num;
    descriptor: I // int type
    flags: ACC_PUBLIC // Modifier 

  private static java.lang.String str;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE, ACC_STATIC
// Method information
  public com.bufan.method.MethadinnecStcuTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: bipush        10
         7: putfield      #2                  // Field num:I
        10: return
      LineNumberTable:
        line 10: 0
        line 12: 4

  public void test1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: bipush        20
         2: istore_1
         3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         6: new           #4                  // class java/lang/StringBuilder
         9: dup
        10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        13: ldc           #6                  // String count =
        15: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        18: iload_1
        19: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        22: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        25: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        28: return
      LineNumberTable:
        line 17: 0
        line 18: 3
        line 19: 28

  public static int test2(int);
    descriptor: (I)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_0
         1: istore_1
         2: bipush        30
         4: istore_2
         5: iload_2
         6: iload_0
         7: idiv
         8: istore_1
         9: goto          17
        12: astore_2
        13: aload_2
        14: invokevirtual #12                 // Method java/lang/Exception.printStackTrace:()V
        17: iload_1
        18: ireturn
      Exception table:
         from    to  target type
             2     9    12   Class java/lang/Exception
      LineNumberTable:
        line 21: 0
        line 23: 2
        line 24: 5
        line 27: 9
        line 25: 12
        line 26: 13
        line 28: 17
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 12
          locals = [ int, int ]
          stack = [ class java/lang/Exception ]
        frame_type = 4 /* same */

  public int compareTo(java.lang.String);
    descriptor: (Ljava/lang/String;)I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=2, args_size=2
         0: iconst_0
         1: ireturn
      LineNumberTable:
        line 33: 0

  public int compareTo(java.lang.Object);
    descriptor: (Ljava/lang/Object;)I
    flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: checkcast     #13                 // class java/lang/String
         5: invokevirtual #14                 // Method compareTo:(Ljava/lang/String;)I
         8: ireturn
      LineNumberTable:
        line 10: 0

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #15 / / internal structure of string test method
         2: putstatic     #16                 // Field str:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 13: 0
}
Signature: #39                          // Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
SourceFile: "MethadinnecStcuTest.java"

The class loaded into the method area records which loader it was loaded by, and the loader will also record which classes it loaded

They record each other

Take a look at the relevant contents of the decompiled bytecode:

Note that this is what we see through bytecode files, not memory. Finally, it will be loaded into the method area by the class loader.

Similarly, the order of bytecode is the same.

Existing num, then str.

The methods are more abundant

We do not declare a constructor in the source code. It will provide us with a parameterless constructor by default

In bytecode files, it is also a method, called init method -- only at the source code level, the constructor is the constructor and the method is the method

Let's take test1() as an example

For example, let's take a look at this static one

This is the bytecode file information you can see before the loader is loaded
We also mentioned that some methods may have exceptions, so there will be an exception table in its bytecode


The exception table is also mentioned in the previous chapter

from,to: from where to where. 2 and 9 are the line numbers in our bytecode file


23-27 are the line numbers in our code

That is, the range that can be wrapped. If there is no exception, execute goto. The corresponding bytecode line number is 17, and the line number in its corresponding code is 28. Then execute the return method. If the exception target is 12 and the code line number corresponding to 12 is 25, an exception occurs.

Class variables of non final (class variables not modified by final)
Class variables (also known as static variables) are variables independent of methods in a class, which are decorated with static.

  • Static variables are associated with the class and loaded with the loading of the class. They become a logical part of the class data.
  • Class variables are shared by all instances of the class, and you can access them even when there are no class instances.

Supplementary note: global constant
The processing method of class variables declared as final is different. Each global constant will be allocated at the time of compilation.

Let's decompile the Order class


In the preparation phase, initialize the static attribute, assign a value by default, and then assign a value of 1 during initialization. If it is final, it will be assigned directly at the preparation stage or at the time of compilation

5. Understanding of constant pool in class file

Running constant pool VS constant pool


Bytecode files are called constant pools

  • Method area, which contains the runtime constant pool.

  • Bytecode file, which contains constant pool.

  • To understand the method area, you need to understand the ClassFile, because the information of the loaded class is in the method area

  • To understand the runtime constant pool in the method area, you need to understand the constant pool in ClassFile. https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

It can be seen that in our bytecode file, it is the one with the largest amount of information


After the constant pool in bytecode file is loaded into the method area in memory, the corresponding structure is called runtime constant pool. So let's figure out the constant pool first

Structure of bytecode file:

The constant pool structure is as follows:

Why do you need to provide a constant pool?
The classes and interfaces in a java source file are compiled to produce a bytecode file. The bytecode in Java needs data support. Usually, this kind of data is too large to be stored directly in the bytecode. In another way, it can be stored in the constant pool. This bytecode contains a reference to the constant pool. The runtime constant pool will be used in dynamic linking, as described earlier.
For example, the following code:


Many classes are used in the classes we write, but the bytecode is only 194 bytes. Obviously, all classes are not compiled into the SimpleClass bytecode. The information we use (classes, constants, etc.) appears as a symbol. This is the symbol reference, and then compiled into the bytecode, so the bytecode file is much smaller. The symbol reference is presented in the constant pool. When it is actually loaded into memory for execution, such as the System class used, the System will be transformed into a direct reference to the System class to be loaded. The position of the System class in the method area (loaded into the real address of memory)

Take test1 for example:

Specifically analyze the operators of test1. Note that when #3, #4, # and so on are used, (# is the index of the constant pool), the structure in the constant pool is actually used. (ldc, operator means loading from constant pool)

Start to analyze #3, and look in the constant pool #3



Found #3, called #54 and #55 again
#54 is System

#55

#55 called #74 again, #74 is an out

#75 specifies that out is a reference type

In this way, all the instructions we need to use are calls to the structures in the constant pool.

It's like the code we write is food, and the content in the constant pool is material. The specific implementation details are transferred from the constant pool

What's in the constant pool?


Summary:
The constant pool can be regarded as a table. The virtual machine instruction finds the class name, method name, parameter type, literal and other types to be executed according to this constant table.

Understanding of runtime constant pool

  • The runtime constant pool (Runtime Constant Poo1) is part of the method area.
  • The constant pool table is a part of the Class file, which is used to store various literal and symbolic references generated during compilation. This part will be stored in the runtime constant pool of 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). Like array items, data items in the pool are accessed by index The runtime constant pool contains many different constants, including numeric literal quantities that have been specified at compile time, and method or field references that can only be obtained after parsing at run time. At this time, it is no longer the symbolic address in the constant pool, but the real address here.
    Another important feature of runtime constant pool compared with class file constant pool is that it is dynamic.
    String.intern() if the string is not in the constant pool, put it in again.
  • 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 the runtime constant pool of a class or interface, if the memory space required to construct the runtime constant pool exceeds the maximum value provided by the method area, the JVM will throw an OutOfMemoryError exception.

Use of illustration example method area

Evolution details of method area in jdk6, jdk7 and jdk8

Why should the position of StringTable be adjusted

jdk7 puts StringTable into heap space. Because the recovery efficiency of the permanent generation is very low, it will be triggered when the GC is full. full gc is triggered when there is insufficient space and permanent generation in the old age. This leads to low recovery efficiency of StringTable. In our development, a large number of strings will be created, and the recycling efficiency is low, resulting in insufficient permanent generation memory. Put it in the heap to reclaim memory in time.

How to prove the existence of static variables

For example, let's see where this byte array will exist?

Take a look at jdk6/7 (the jdk6 setting parameters are the same as jdk7), and the new byte objects are placed in the heap

Take a look at jdk8. The new byte object is also placed in the older generation heap

Summary: the object entity corresponding to the static reference (new object) always has heap space
Some students want to ask, don't static variables exist in the permanent generation in jdk6
Let me solve the puzzle: what is put in the permanent generation refers to the variable name arr, which has a position change according to the jdk version. It is not the object it refers to, but the objects are placed in the heap space (if there is no escape, they will be allocated on the stack).

Take an example:

Garbage collection behavior in method area

Some people think that the method area (such as meta space or permanent generation in HotSpot virtual machine) has no garbage collection behavior, but it is not. The constraint of the Java virtual machine specification on the method area is very loose. It is mentioned that the virtual machine is not required to implement garbage collection in the method area. In fact, there are collectors that do not implement or fail to fully implement method area type unloading (for example, ZGC collectors in JDK 11 do not support class unloading).
Generally speaking, the recovery effect of * * this area is difficult to be satisfactory, especially for the type of unloading, the conditions are quite harsh. However, the recycling of this part of the area is sometimes necessary** Several serious bugs in the Bug list of Sun company in the past are memory leaks caused by the incomplete recycling of this area by the lower version of HotSpot virtual machine.
Garbage collection in the method area mainly collects two parts: discarded constants in the constant pool and types that are no longer used.

● first, let's talk about the two main types of constants stored in the constant pool in the method area: literal quantity and symbol reference. Literal quantity is close to the constant concept of Java language level, such as text string, constant value declared as final, etc. Symbolic reference belongs to the concept of compilation principle, including the following three types of constants:
1. Fully qualified names of classes and interfaces
2. Field name and descriptor
3. Name and descriptor of the method
● the recycling strategy of 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 discarded constants is very similar to recycling objects in the Java heap.
● it is relatively simple to determine whether a constant is "obsolete", and the conditions to determine whether a type belongs to "class no longer used" are more stringent. 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 of replaceable class loader, such as OSGi and JSP reload.
The corresponding Java 1ang . The class object is not referenced anywhere, and the methods of this class cannot be accessed anywhere through reflection.
● Java virtual machine is allowed to recycle useless classes that meet the above three conditions. What we say here is only "allowed", not the same as objects. If there is no reference, it will be recycled. As for whether to recycle types, the HotSpot virtual machine provides the - Xnoclassgc parameter to control. You can also use - verbose:class and - XX: + traceclass loading, - XX: +TraceClassUnLoading to view class loading and unloading information
● in scenarios where bytecode frameworks such as reflection, dynamic proxy and CGLib are widely used, and frequent custom class loaders such as JSP and oSGi are dynamically generated, the Java virtual machine is usually required to have the ability of type unloading to ensure that it will not cause too much memory pressure on the method area.

summary


Summary of runtime data area and description of common interview questions

Baidu
Three sides: let's talk about the JVM memory model. What areas are there? What do you do separately?
Ant gold suit:
Memory generation improvement of Java 8
Which areas of JVM memory are divided into and what is the role of each area?
One side: JVM memory distribution / memory structure? What is the difference between stack and heap? Heap structure? Why two survivor areas?
Two sides: proportional distribution of Eden and survival
Xiaomi:
jvm memory partition, why should there be new generation and old generation
Byte runout:
Two sides: Java memory partition
Side 2: talk about the jvm runtime database area
When will the object enter the elderly generation?
JD.COM:
Memory structure of JVM, Eden and Survivor ratio.
Why should JVM memory be divided into new generation, old generation and persistent generation. Why is it divided into Eden and Survivor in the Cenozoic.
Tmall:
One side: the Jvm memory model and partitions need to be detailed about what to put in each area.
One side: what changes have been made to the memory model of the JVM and Java 8
Pinduoduo:
Which areas of JVM memory are divided into and what is the role of each area?
Meituan:
java memory allocation
Will garbage collection occur in the permanent generation of the jvm
One side: jvm memory partition, why should there be new generation and old generation?

Topics: jvm