Method area of jvm

Method area of jvm

definition

(1) The method area, like the java heap, is a memory area shared by all threads
(2) The method area is created when the jvm starts, and its actual physical memory space can be discontinuous like the java heap area
(3) The size of the method area, like the heap space, can be fixed or expanded
(4) 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
Before java8 (java.lang.OutOfMemoryError:PermGen space) or after java8 (java.lang.OutOfMemoryError:Metaspace)
(5) Closing the jvm frees up memory in this area

position

jdk1.6 and jdk1 8. Different location of method area

difference

The evolution of the method area can be seen from the figure: before jdk7, the implementation of the method area was a permanent generation. From jdk8, the implementation of the method area used meta space to replace the permanent generation. The main difference between the permanent generation and meta space is that the meta space is not in the memory set by the virtual machine, but in the local memory. If the new memory allocation requirements cannot be met, an OOM error will also be reported.

Replacement reason

Why should permanent generation be replaced by meta space:
(1) The space size setting of the permanent generation is difficult to determine. For example, in some scenarios, if there are too many dynamically loaded classes, an OOM error will occur, and the meta space directly uses local memory. By default, the size of the meta space is limited only by local memory
(2) It is difficult to tune the permanent generation; Tuning is to reduce FullGC. If the permanent generation triggers FullGC frequently, it will make it difficult to tune the permanent generation
(3) Merge the codes of HotSpot and JRockit; JRockit has never had a permanent generation

Why should StringTable be put in the heap

Because the recovery frequency of the permanent generation is relatively low, it will only be recovered when FullGC is used. FullGC will only be triggered when the permanent generation is old or there is insufficient space. There are a large number of strings in stringtable. If a large number of strings are created and placed in the permanent generation, the space of the permanent generation will be insufficient due to the low recycling frequency of the permanent generation.
  if you put it in the heap, you can reclaim the memory in time.

component

It is used to store the type information, constants, static variables and JIT code loaded by the virtual machine
(1) Type information: each loaded type (class, interface, enum, enum, annotation)
(2) Domain information
(3) Method information (method name, return type, modifier, etc.)
(4) Static variables and class relationships are together. They are loaded with the loading of classes and become a logical part of class data. Class variables are shared by all instances. Even if there is no class instance, you can access its global constants (static final). Each global constant is determined during compilation

Constant pool

The constant pool is a table. The virtual machine instruction finds the class name, method name, parameter type, literal and other information to be executed according to this constant table
For example, execute hello word

 public static void main(String[] args) {
        System.out.println("Hello word");
    }

Use javap - V helloword Class view binaries

Classfile /E:/proxxy/target/classes/com/StringTable/HelloWord.class
  Last modified 2022-2-23; size 561 bytes
  MD5 checksum c115752e064012c1ab2f0ab073df470f
  Compiled from "HelloWord.java"
public class com.StringTable.HelloWord
  SourceFile: "HelloWord.java"
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#20         //  java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        //  java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            //  Hello word
   #4 = Methodref          #24.#25        //  java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            //  com/StringTable/HelloWord
   #6 = Class              #27            //  java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/StringTable/HelloWord;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8               HelloWord.java
  #20 = NameAndType        #7:#8          //  "<init>":()V
  #21 = Class              #28            //  java/lang/System
  #22 = NameAndType        #29:#30        //  out:Ljava/io/PrintStream;
  #23 = Utf8               Hello word
  #24 = Class              #31            //  java/io/PrintStream
  #25 = NameAndType        #32:#33        //  println:(Ljava/lang/String;)V
  #26 = Utf8               com/StringTable/HelloWord
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (Ljava/lang/String;)V
{
  public com.StringTable.HelloWord();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 8: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       5     0  this   Lcom/StringTable/HelloWord;

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello word
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 10: 0
        line 11: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       9     0  args   [Ljava/lang/String;
}


If you execute 0: getstatic #2, you will find #2 = fieldref #21 in Constant pool:# 22 then find #21 = Class #28 #22 = NameAndType #29:#30 and then continue to find #28 = Utf8 java/lang/System #29 = Utf8 out #30 = Utf8 Ljava/io/PrintStream; So far, this paragraph has been executed: it means to execute system The out method is similar to the following..

Runtime Constant Pool

Constant pool in * In the class file, when the class is loaded, its constant pool information will be put into the runtime constant pool, and the symbolic address in it will be changed into the real address

StringTable

String constant pool (string pool), 1.8 is put into the heap. The reference value rather than the specific instance object is stored in the string constant pool. The specific instance object is stored in a space opened up in the heap. Note that it is a different concept from the runtime constant pool. The runtime constant pool is in the constant pool during class loading, such as #2 becoming a real address;
Common interview questions:

       String s1="ab";
        String s2=new String("ab");
          String s3="a"+"b";
        System.out.println(s1==s2);
        System.out.println(s1==s3);

To see this question, you must first understand how the jvm puts strings into the string constant pool
Creation process:
Whenever we create a String constant, the JVM will first check the String constant pool. If the String is in the constant pool, it will directly return the instance reference in the constant pool. If the String does not exist in the constant pool, the String is instantiated and placed in the constant pool. Due to the immutability of String, we can be quite sure that there must not be two identical strings in the constant pool.

String s1="ab";
The creation process is:
1. First, find out whether there is a string object with "ab" content in the constant pool.
2. If it does not exist, create "ab" in the constant pool and let s1 reference the object.
String s2=new String("ab");
Creation process:
1. First, create a specified object "ab" in the heap (not a constant pool) and have the s2 reference point to it.
2. Check the string constant pool to see if there is a string object with content "ab".
3. If it exists, let the string object created in the heap reference the object of the string constant pool.
String s3="a"+"b";
Creation process
1. First, find out whether there is a string object with "ab" content in the constant pool.
2. If it does not exist, create "ab" in the constant pool and let s1 reference the object.
Why go to "ab" directly? Because "a" and "b" are constants in javac optimization during compilation, they are determined as "ab" during compilation
The running result is false or true
String s2=new String(“ab”); How many objects have been created
The answer is 1. First, create a specified object "ab" in the heap (not the constant pool) and let the s2 reference point to the object (1 created). Check whether there is a String object with content "ab" in the String constant pool, because String s1="ab"; The String object of "ab" has been created in the String constant pool, so the String object created in the heap refers to the object of the String constant pool. (not created) String s1="ab" if String s2=new String("ab"); If it does not exist, add a String object with "abc" in the constant pool and reference the String object in the heap

intern method

 String s=new String("a")+new String("b");
        String s1=s.intern();
        System.out.println(s=="ab");
        System.out.println(s1=="ab");

Analyze String s=new String("a") + new String("b");
Obviously: there are ["a", "B"] in the string pool, and there are new String("a"), new String("B") and s in the heap, which is equivalent to StringBuilder append(“a”). append(“b”). toString(); new String("ab")
Bytecode files are not analyzed one by one. Refer to the above example

intern() tries to put this string object into the string pool. If there is one, it will not be put in. If there is no one, it will be put into the string pool, and the object of the string pool will be returned (jdk1.7 later version)
So the execution result is true, true
What if x is defined as ab in advance

 String x="ab";
        String s=new String("a")+new String("b");
        String s1=s.intern();
        System.out.println(s==x);
        System.out.println(s1==x);

The execution result is false or true
jdk1. Version 6 intern() tries to put this string object into the string pool. If there is one, it will not be put in. If there is no one, it will put a copy of s into the string pool and return the string pool object

 String s=new String("a")+new String("b");
        String s1=s.intern();
        System.out.println(s=="ab");
        System.out.println(s1=="ab");

The execution result is false or true

Keywords: Java jvm Back-end

Added by jd6th on Wed, 23 Feb 2022 11:07:24 +0200