Runtime data area (method area)

The virtual machine specification describes the method area

The Java Virtual Machine Specification makes it clear that “although all method areas are logically part of the heap, some simple implementations may not choose to garbage collect or compress.” In the case of HotSpotJVM, however, the method area also has an alias called non-heap in order to separate it from the Heap. Therefore, the method area is treated as a memory space independent of the Java heap.

The main points of

  • The Method Area, like the Java heap, is a memory Area shared by all threads.
  • The method area is created at JVM startup time, and its actual physical memory space can be discontinuous just like the Java heap area.
  • The size of the method area, like the heap space, can be fixed size or scalable.
  • The size of the method area determines how many classes the system can hold. If too many classes are defined and the method area overruns, the vm will also throw an overflow error:
    • Java. Lang. OutOfMemoryError: PermGen space () before jdk7
    • Java. Lang. OutOfMemoryError: Metaspace (after jdk8)
  • Overflow scenario:
    • Load a large number of third-party JAR packages;
    • Too many projects for Tomcat deployment (30-50)
    • A number of dynamically generated reflection classes
  • Shutting down the JVM frees up memory in this region.

View and set the method area size

  1. Jdk7 and before:
  • -xx :PermSize to set the permanent generation initial allocation space. The default value is 20.75m,
  • -xx :MaxPermSize to set the maximum space available for permanent generation. The default is 64MB for 32-bit machines and 82M for 64-bit machines
  • When the amount of class information loaded by the JVM exceeds this value, the EXCEPTION OutOfMemoryError:PermGen space is reported.
  1. Jdk8 and beyond:
  • -xx :MetaspaceSize Sets the MetaspaceSize initialization space

  • -xx :MaxMetaspaceSize Sets the maximum memory size of the meta space

  • The default value depends on the platform. On Windows, -xx :MetaspaceSize is about 20.79M; -xx: The value of MaxMetaspaceSize is large on Windows; If it is -1, there is no limit.

  • Unlike the permanent generation, if the size is not specified, the virtual machine will use up all available system memory by default. If an overflow occurs in the metadata area, the VM will also throw OutOfMemoryError: Metaspace

  • -xx :MetaspaceSize: sets the initial size of the meta space. For a 64-bit server-side JVM, the default -xx :MetaspaceSize value is about 20.79m. This is the initial high watermark. Once this watermark is reached, Full GC is fired and useless classes are unloaded (i.e. the class loaders corresponding to these classes are no longer alive), and the high watermark is reset. The value of the new high water mark depends on how much space is freed after GC. If there is not enough space to free, increase the value as soon as MaxMetaspaceSize is not exceeded. If too much space is freed, lower the value.

  • If the initial high water level is set too low, the above high water level adjustment will occur many times. Multiple calls to Full GC can be observed through the logs of the garbage collector. To avoid frequent GC, it is recommended to set -xx :MetaspaceSize to a relatively high value. It is generally recommended to set MetaspaceSize and MaxMetaspaceSize to the same value in the JVM parameters. For a machine with 8 gb of physical memory, this value is usually set to 256M.

3. Check the size in window

Method area OOM example

Operation parameters

-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m

/** * test method area: * -xx :PermSize= 10m-xx :MaxPermSize= 10m-xx **  * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m * */ public class OOMTest extends ClassLoader { public static void main(String[] args) { int j = 0; try { OOMTest test = new OOMTest(); for (int i = 0; i < 10000; I++) {// create a ClassWriter object to generate binary bytecode for the ClassWriter ClassWriter = new ClassWriter(0); // Specify the version number, modifiers, class name, package name, superclass, Interface classWriter.visit(opcodes.v1_6, opcodes.acc_public, "Class" + I, null, "Java /lang/Object", null); Byte [] byte[] code = classwriter.tobyteArray (); // Return byte[] byte[] code = classwriter.tobyteArray (); Test.defineclass ("Class" + I, code, 0, code.length); / / Class object j++; } } finally { System.out.println(j); }}}Copy the code

How to solve the OOM area

  1. To resolve a 00M exception or heap space exception, the usual approach is to first analyze the dumped heap dump snapshot with a Memory image analysis tool (such as Eclipse Memory Analyzer), focusing on confirming whether the objects in Memory are necessary. In other words, we should first identify whether there is a Memory Leak or a Memory 0verflow.

  2. In the case of a memory leak, you can further look through the tool to see the chain of references from the leak object to GC Roots. You can then find out what path the leaking objects are associated with the GCRoots and cause the garbage collector to fail to collect them automatically. With information about the type of the leaking object and the chain of GCRoots references, you can locate the leaking code more accurately.

  3. If there are no memory leaks, in other words, objects in memory really must still be alive, then you should check the heap parameters of the virtual machine (-xmx and -xMS) to see if they can be increased compared to the physical memory of the machine, and check the code to see if some objects are living too long and holding state for too long. Try to reduce the runtime memory consumption of the program.

Gleanings – The difference between memory leaks and memory spills

  • Memory Leak: After a program uses Memory, an object becomes useless, but it is not collected by the GC. It always occupies Memory, and the accumulation of Memory leaks will eventually lead to a Memory Leak.
  • Memory Overflow: An error that occurs when a program cannot obtain enough Memory while running. Memory overruns usually occur in the old days when there is still no memory space to hold new Java objects after garbage collection. This is usually caused by a memory leak that causes stack memory to grow, causing a memory overflow

Methods area

Based on the Hotspot1.8

A meta information

The type information

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

  • The full valid name of the type (full name = package name. The name of the class)
  • The full valid name of the type’s immediate superclass (for interface or Java.lang.object, there is no superclass)
  • Modifiers for this type (some subset of public, abstract, final)
  • An ordered list of direct interfaces of this type

Domain information

The JVM must store information about all fields of the type and the order in which the fields are declared in the method area.

  • Field declaration order
  • Domain name
  • Domain types
  • Field modifiers (some subset of public, private,protected, static, final, volatile, transient)

Note: Field = Field = attribute = member variable

Methods information

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

  • Method names
  • Method return type (or void)
  • Number and type of method parameters (in order)
  • Modifiers for methods (a subset of public, private, protected, static, final,synchronized, native, abstract)
  • Method bytecodes, operand stack, local variable table, and size (except for abstract and native methods)
  • Exception table (except for abstract and native methods) : the start and end position of each exception handling, the offset address of the code handling in the program counter, and the constant pool index of the exception class that was caught

Method table

To improve access efficiency, the data information structure stored in the method area must be carefully designed. In addition to the structures discussed above, the JVM implementer can add some other data structures, such as method tables. The JVM adds a method table to the type information of each loaded non-virtual class. The method table is a set of direct references to the class instance methods (including methods inherited from the parent class). The JVM can quickly activate instance methods through method tables

A reference to the class loader

The JVM must know whether a type is loaded by the boot loader or by the user class loader. If a type is loaded by a user classloader, the JVM stores a reference to that classloader in the method area as part of the type information. The JVM needs this information for dynamic linking. When parsing a reference from one type to another, the JVM needs to ensure that the classloaders for both types are the same. This is critical to the way the JVM differentiates namespaces.

Class a reference to an instance of the Class

The JVM creates an instance of Java.lang.class (stored on the heap) for each loaded Class. The JVM must somehow associate this instance of Class with the type data (Class metadata) stored in the method area. Therefore, the Class metadata holds a reference to the Class object;

Runtime constant pool

The constant pool in the class file is loaded into memory by the JVM virtual machine after the class load operation is completed and stored in the method area. We often say that the constant pool is the runtime constant pool in the method area.

The run-time constant pool corresponds to the class file constant pool, which is built from the class file constant pool.

The runtime constant pool is part of the method area. A constant pool in the CLass file that holds the various literal and symbolic references generated at compile time. This will be stored in the run-time constant pool in the method area after the CLass is loaded.

literal

  • Text strings, constant values that are declared final, values of basic data types, etc

In computer science, a literal is a notation used to express a fixed value in source code.

How to distinguish: values of the eight basic types on the right of the equal sign, string values, and values of constants declared as final. Such as:

final int a = 10; String b = "Hello world!" ; // hello world! As the literalCopy the code

Symbolic reference

  • Fully qualified names of classes and interfaces
  • The name and descriptor of the field
  • The name and descriptor of the method

A symbolic reference is a set of symbols that describe the object being referenced. A symbol can be any literal, as long as it is used to locate the object unambiguously. For example, it appears in Class files as constants of types CONSTANT_Class_info, CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and so on. Symbolic references are independent of the memory layout of the virtual machine, and the target of the reference is not necessarily loaded into memory. In Java, a Java class is compiled into a class file. At compile time, the Java class does not know the actual address of the referenced class, so only symbolic references can be used instead. For example, the org.simple.People class references the org.simple.Language class. At compile time, the People class does not know the actual memory address of the Language class. Therefore, the address of a Language class can only be represented by the symbol org.simple.language (which is actually represented by a constant like CONSTANT_Class_info). The memory layout of the various virtual machine implementations may differ, but they will all accept the same symbolic references because the literal form of symbolic references is clearly defined in the Java virtual Machine specification’s Class file format.

Runtime constant pool relative to the CLass file another important feature of the constant pool is dynamic, the Java language does not require constant must only compile time to produce, is not preset constant pool into the CLass file content can enter method area runtime constant pool, runtime might also put new constants in a pool, One feature that developers have taken advantage of more often is the String class’s intern() method.

JIT code cache

CodeCache is a code cache that caches code compiled by the JIT(Just in Time) compiler. In short, codeCache is the native code generated by the JIT. Of course the JNI(Java Native Interface) machine code is also in the codeCache, but the JIT compiled native code is the main part.

When frequently used Code, known as Hot Spot Code, reaches a certain threshold, the JVM compiles local platform-based machine Code and performs various levels of optimization to improve execution efficiency.

There are also two types of hot codes:

  • A method that is called multiple times
  • The body of a loop that is executed multiple times

Method area jdK7 and JDK8 difference

  • In jdk7 and before, it was customary to refer to the method area as the permanent generation. Starting with JDK8, the use of meta space replaces the permanent generation.

  • In essence, metaclasses are similar to permanents in that they are implementations of method areas in the JVM specification. However, the biggest difference between the meta-space and the permanent generation is that the meta-space is not in the memory set by the virtual machine, but uses local memory.

  • At runtime before JDK1.7 the constant pool logic contains string constant pools stored in the method area, at which time the hotspot virtual machine implements the method area as a permanent generation.

  • In JDK1.7 the string constant pool is taken out of the method area and into the heap, there is no mention of the runtime constant pool, that is, the string constant pool is taken out of the heap separately, and the rest of the runtime constant pool is still in the method area, which is the permanent generation in hotspot.

  • In essence, method extents and permanent generations are not equivalent. Only for Hotspot. The Java Virtual Machine Specification has no uniform requirements on how to implement method areas. For example, the concept of permanent generations does not exist in BEA JRockit/ IBM J9. In principle, how to implement the method area belongs to the details of virtual machine implementation, which is not subject to the Java Virtual Machine Specification and does not require unification. Method areas are just a specification, and implementations vary across different virtual machines, such as permanent generations and meta-spaces.

  • Now, the use of permanent generation, is not a good idea. OOM (-xx :MaxPermSize upper limit)

  • According to the Java Virtual Machine specification, an OOM exception will be thrown if the method area does not meet the new memory allocation requirements.

Method area evolution of different versions

version change
Jdk1.6 and before There is a permanent generation. Static variables are stored in the permanent generation
jdk1.7 There are permanent generations, but have been gradually “depermanent generation”, string constant pool, static variables removed, stored in the heap
Jdk1.8 and after There is no permanent generation. Type information, fields, methods, and constants are stored in the local memory meta space, but the string constant pool and static variables remain in the heap

Conclusion:

  • Permanent generation is changed to meta-space
  • Metadata using direct memory (local memory, system memory)

The official website explains moving static variables to the heap

Currently static fields are stored in the instanceKlass but when those are moved into native memory we'd have to have a new card mark strategy for static fields. This could be something like setting a flag in the instanceKlass and then rescanning every klass during a GC which seems expensive or marking the card for the java.lang.Class then making sure to scan the instanceKlass when scanning the Class. If we move them into the Class then almost all the existing machinery works exactly as it always has. The only execution difference is which constant is materialized for the field access.

The official website for string constant pool to move to the heap description

Interned strings are currently stored in the permanent generation. A new approach for managing meta-data is being designed and it requires interned strings to live elsewhere in the the heap (young gen and/or old gen).

What should be replaced by the meta-space permanently

  1. Setting the space size for a permanent generation is difficult to determine.

In some scenarios, if you load too many classes dynamically, it is easy to generate OOM in Perm zone. In an actual web engineering, for example, because the function point, in the process of operation, to keep the dynamic load many classes, often fatal error: Java. Lang. OutOfMemoryError: PermGen space

The meta-space is not in the virtual machine, but local memory is used. By default, the size of the meta space is limited only by local memory.

  1. Tuning a permanent generation is difficult.

Why is StringTable heaped

Jdk7 places StringTable in the heap space. Because the collection efficiency of permanent generation is very low, it will only be triggered during full GC. Full GC, on the other hand, is triggered when the old generation is short of space and the permanent generation is short. This makes the StringTable collection inefficient. However, in our development, a large number of strings will be created, which leads to low recycling efficiency and insufficient memory for permanent generation. Put it in the heap to reclaim memory in time.

Symbolic references and direct references

String site="www.flydean.com"

The above string “www.flydean.com” can be regarded as a static constant, since it does not change and is displayed as it is.

The name “site” of the string above is a symbolic reference that needs to be resolved at run time. Why?

Since the value of site can be changed, we cannot determine its real value at the first time, and it needs to be resolved in dynamic operation, and the parsing phase is the phase to transform the symbolic reference into the real address.

  1. Symbolic reference

A symbolic reference is a set of symbols that describe the object being referenced. A symbol can be any literal, as long as it is used to locate the object unambiguously. For example, it appears in Class files as constants of types CONSTANT_Class_info, CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and so on. Symbolic references are independent of the memory layout of the virtual machine, and the target of the reference is not necessarily loaded into memory. In Java, a Java class is compiled into a class file. At compile time, the Java class does not know the actual address of the referenced class, so only symbolic references can be used instead. For example, the org.simple.People class references the org.simple.Language class. At compile time, the People class does not know the actual memory address of the Language class. Therefore, the address of a Language class can only be represented by the symbol org.simple.language (which is actually represented by a constant like CONSTANT_Class_info). The memory layout of the various virtual machine implementations may differ, but they will all accept the same symbolic references because the literal form of symbolic references is clearly defined in the Java virtual Machine specification’s Class file format.

  1. Direct reference

Direct references are related to the layout of the virtual machine. The same symbolic reference will not translate the same direct reference across different virtual machine instances. If there is a direct reference, the target of the reference must already be loaded into memory.

Direct references can be implemented in different ways:

  • A pointer directly to a target (for example, a direct reference to a “type” [Class object], a Class variable, or a Class method might be a pointer to a method area)
  • Relative offsets (for example, direct references to instance variables and instance methods are offsets)
  • A handle that indirectly locates the target
  1. Structure description
  • String
    • Constructed from the CONSTANT_String_info structure in class:

      CONSTANT_String_info {
                u1 tag;
                u2 string_index;
                }
      Copy the code

Tag is the tag of the structure, and string_index is the index of the string in the class constant pool.

The contents of the class constant pool corresponding to string_index are a CONSTANT_Utf8_info structure.

    CONSTANT_Utf8_info {
        u1 tag;
        u2 length;
        u1 bytes[length];
        }
Copy the code
  • Digital constant

    • The numeric constants are built from the class file CONSTANT_Integer_info, CONSTANT_Float_info, CONSTANT_Long_info, and CONSTANT_Double_info.
  • Symbolic reference (built from constant_pool in class.)

    • The symbolic references to classes and interfaces are from CONSTANT_Class_info.

    • The references to the fields in class and interface are from CONSTANT_Fieldref_info.

    • The reference to the method in class is from CONSTANT_Methodref_info.

    • The reference to the method in interface is from CONSTANT_InterfaceMethodref_info.

    • The reference to the method handle is from CONSTANT_MethodHandle_info.

    • The reference to the method type is from CONSTANT_MethodType_info.

    • The symbolic reference to dynamically computed constants is from CONSTANT_MethodType_info.

    • The reference to a dynamically computed call Site is from CONSTANT_InvokeDynamic_info.

Variables, static variables, constants, literals

  1. variable

Some data can change or be assigned values while the program is running. These are called variables. Such as:

int a;

String b;

  1. Static variables (class variables)

Static modifies a variable

Private static String STR = "static ";

Three constants

In Java, the term “final” is used to refer to variables modified with the final keyword (or “constant” in C). Because of the immutable nature of “final”, the value of a final class variable is determined during compilation, stored in the class’s constant pool, and then copied into the run-time constant pool in the method area when the class is loaded. Final class variables are stored ina pool of runtime constants, and each class that uses them holds a reference to them

final int a;

final String b;

  1. literal

In computer science, a literal is a notation used to express a fixed value in source code.

How to distinguish: values of the eight basic types on the right of the equal sign, string values, and values of constants declared as final. Such as:

final int a = 10; // A is constant and 10 is literal

String b = "Hello world!" ; // hello world! As the literal

Static variables are different from constants

  • Static variables (class variables) : Are associated with a class and become a logical part of the class data as the class is loaded. Class variables are shared by all instances of the class and you can access them even when there is no instance of the class. The static modifier. Default values are initialized in the preparation phase, and explicit values are assigned in the initialization phase

  • Constants (global constants) : Class variables that are declared final are treated differently; each global constant is allocated at compile time. Static final modifier.

    Public class MethodAreaTest {public static void main(String[] args) {Order Order = null; Static variables and static methods are related only to the class, not to the instance order.hello(); System.out.println(order.count); } } class Order { public static int count = 1; public static final int number = 2; public static void hello() { System.out.println("hello!" ); }}Copy the code

Output results:

    hello!
    1
Copy the code

Conclusion: Static variables can be called by object or by class name.

Static variable, member variable, local variable storage location?

Static variables (class variables)

  • Defined in a class, outside a method, with the keyword static modifier, with a default initial value.
  • It can be called by object or by class name.
  • The life cycle lives and dies with the class.
  • Objects are stored in the method area and references are held in the Class object

Member variables (instance variables)

  • Defined in classes and outside methods, with default initial values.
  • Instance variables are accessed by reference to the object.
  • It is created as the object is created, disappears as the object disappears, and exists in the heap memory where the object resides.

A local variable

  • A parameter defined in a method, or a method parameter, has no initialization value.

  • The life cycle lives and dies with the method.

  • Put it on the stack. A reference to a local object refers to an address in the heap that is stored on the stack.

    /** * conclusion: * static variable references to object entities always exist in heap space ** jdk7: * -xms200m -xmx200m -xx :PermSize=300m -xx :MaxPermSize=300m -xx :+PrintGCDetails * JDK 8:  * -Xms200m -Xmx200m -XX:MetaspaceSize=300m -XX:MaxMetaspaceSize=300m -XX:+PrintGCDetails */ public class StaticFieldTest { private static byte[] arr = new byte[1024 * 1024 * 100]; //100MB public static void main(String[] args) { System.out.println(StaticFieldTest.arr); }}Copy the code

Running parameters:

-Xms200m -Xmx200m -XX:MetaspaceSize=300m -XX:MaxMetaspaceSize=300m -XX:+PrintGCDetails

[B@1b6d3586 Heap PSYoungGen total 59904K, used 4150K [0x00000000fbd80000, 0x0000000100000000, 0x0000000100000000) eden space 51712K, 8%, informs [x00000000fbd80000 0, 0 x00000000fc18dbf0, 0 x00000000ff000000) from space 8192 k, 0%, informs [x0000000100000000 x00000000ff800000 0, 0 x00000000ff800000, 0) to space 8192 k, 0%, informs [x00000000ff000000 0, 0 x00000000ff000000, 0 x00000000ff800000) ParOldGen total 136704 k, used 102400K [0x00000000f3800000, 0x00000000fbd80000, 0x00000000fbd80000) object space 136704K, 74%, informs [x00000000f3800000 0, 0 x00000000f9c00010, 0 x00000000fbd80000) Metaspace informs the 3219 k, capacity 4496 k, committed 4864K, reserved 1056768K class space used 350K, capacity 388K, committed 512K, reserved 1048576K Process finished with exit code 0Copy the code

ParOldGen Total 136704K, Used 102400K is the old area where arR object storage is located.

Conclusion: Static variables generated by new always exist in the heap, arR is bound to the Class object, and the Class object also exists in the heap

Class object

What is a Class object

In Class Loading, the end product of Loading is a Java.lang. Class object, which is our external interface to the Class metadata in the method area. We need this object to access the Class fields, methods, run-time constant pool, and so on.

A class is a description of a class of things, and a class contains information about a class of things, such as a car. The class contains information about the type of car, its purpose, its behavior, and it can run on the road. The fish class, which contains information about the species, name, and behavior of the fish, can swim in the water.

The Class Class is used to describe the Class information. Class is also a type that describes the characteristics of a Class.

In terms of class loading and object creation. After each class file is written, it is first compiled into a.class file. At runtime, the.class file is loaded into the JVM. If the class is loaded for the first time, a java.lang. class object is instantiated in the Java heap memory to access the class data in the method area. When you use the new keyword to create an object of a Class, you will first go to the corresponding Class object to obtain the information of the Class, and then create the object. Therefore, a Class object can be regarded as a template of a Class. Objects of the same Class are created using this template. There can be many objects created by a Class, but there is only one template, which means there is only one Class object for each Class.

A Java file is compiled and loaded to create a Class object. When the Class of the Java file needs to create an object, that is, using the new keyword to create an object, it retrieves the information in the Class object that has already been created. The important thing to note here is that information about a Class object is obtained at runtime, and only at runtime can information about a Class be obtained through Class.

Method to get a Class

  1. Class.forname (” Class “); Gets the Class object from the Class name string.

  2. Get a Class object of that type by calling getClass() on the object of that Class

  3. Get a Class object directly by type

Using Class methods

Class objects are distinguished from Class meta information

  • Class objects are stored in the heap, not the method area.
  • Class meta information exists in the method area (Class meta information is not a Class object of the Class! The Class object is the final product loaded) : the method code of the Class, variable names, method names, access permissions, return values, and so on are all in the method area.
  • The class Pointer in the object header points directly to the class meta information in the method area. Is not a Class object in the heap.

Refer to related articles:

Are Hotpot Java VIRTUAL machine Class objects in the method area or in the heap?

Class loading and Class objects

When a Class is loaded by the JVM, an instance of that Class is created in the heap. What does this Class instance do?

Explore where variables are stored

Understanding the JAVA Virtual Machine Version 3

/** * "Java virtual Machine" in the case: * staticObj, instanceObj, localObj where to store? */ public class StaticObjTest {static class Test {static ObjectHolder staticObj = new ObjectHolder(); ObjectHolder instanceObj = new ObjectHolder(); Void foo() {// local variable ObjectHolder localObj = new ObjectHolder(); System.out.println("done"); } } private static class ObjectHolder { } public static void main(String[] args) { Test test = new StaticObjTest.Test();  test.foo(); }}Copy the code

Conclusion:

  • As long as it’s a new instance object, it’s bound to be allocated in the Java heap.
  • After static variable references are stored in the Class object (Hotspot) with the type information for Test, the Class object is in the heap
  • Member variable references are stored in the Java heap along with the object instance of Test
  • Method variables are stored in the stack frame local variable table

Articles on static variables and Class object storage areas

www.zhihu.com/question/59…

Blog.csdn.net/Xu_JL1997/a…

Conclusion:

The Java Virtual Machine Specification does not specify how to implement the method area. Different VMS can flexibly use the method area.

  1. JDK7 and laterThe Hotspot virtual machine, and store static variables in the heap with Class objects instead of in the meta space.
  2. When a class is loaded, the.class file is loaded into memory and a class object is built in the heap.
  3. A static variable is found to be bound to a Class object in the heap. The static variable is found to be bound to a Class object in the heap.
  4. Move static variables, stringtables, from the method area to the heap, mainly to GC, the method area can GC, but only full GC, very low frequency.

For example,

Public class PersonDemo {public static void main(String[] args) {// the local variable p and parameter args are in the stack frame of the main method // The new Person() object allocates space in the heap Person p = new Person(); Int [] sum = new int[10]; int[] sum = new int[10]; }} class Person {// private String name; private int age; Private static String name1 = "cn"; private static String name1 = "cn"; // The class variable (reference type)name2 is in the heap; Private static String name2 = new String("cn"); private static String name2 = new String("cn"); private static String name2 = new String("cn"); //num = new int[10] private int[] num = new int[10]; Person(String name,int age) {this.name = name; this.name = name; this.name = name; this.name = name; this.name = name; this.name = name; this.age = age; } public void setName(String name) {this.name = name; Public void speak() {system.out.println (this.name+"..."); +this.age); } public static void showCountry() {system.out.println ("country="+country); }}Copy the code

Constant pool – Runtime constant pool – String constant pool

  • Method area, which contains a pool of runtime constants. A bytecode file that contains a constant pool.
  • To understand the method area, you need to understand the ClassFile, because the information for loading the class is in the method area.
  • To understand the pool of runtime constants in the method area, you need to understand the pool of constants in classfiles.

Virtual machine specification url: docs.oracle.com/javase/spec…

Understand method area structure from bytecode

– javap decompiling

  • The source code

    package com.atguigu.java; import java.io.Serializable; Public class MethodInnerStrucTest extends Object Implements Comparable<String>, Public int num = 10; Serializable {// attribute public int num = 10; Private static String STR = ""; 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; }}Copy the code
  • Decompiling: javap – v – p MethodInnerstrucTest. Class

        Classfile /E:/gitee-project/JVMDemo/out/production/chapter09/com/atguigu/java/MethodInnerStrucTest.class
        Last modified 2021-8-8; size 1626 bytes
        MD5 checksum e1c1d3676c744536b4115807127aeb77
        Compiled from "MethodInnerStrucTest.java"
        //类型信息
      public class com.atguigu.java.MethodInnerStrucTest extends java.lang.Object implements java.lang.Comparable<java.lang.String>, java.io.Serializable
        minor version: 0
        major version: 52
        flags: ACC_PUBLIC, ACC_SUPER
        //常量池
      Constant pool:
         #1 = Methodref          #18.#52        // java/lang/Object."<init>":()V
         #2 = Fieldref           #17.#53        // com/atguigu/java/MethodInnerStrucTest.num:I
         #3 = Fieldref           #54.#55        // java/lang/System.out:Ljava/io/PrintStream;
         #4 = Class              #56            // java/lang/StringBuilder
         #5 = Methodref          #4.#52         // java/lang/StringBuilder."<init>":()V
         #6 = String             #57            // count =
         #7 = Methodref          #4.#58         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
         #8 = Methodref          #4.#59         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
         #9 = Methodref          #4.#60         // java/lang/StringBuilder.toString:()Ljava/lang/String;
        #10 = Methodref          #61.#62        // java/io/PrintStream.println:(Ljava/lang/String;)V
        #11 = Class              #63            // java/lang/Exception
        #12 = Methodref          #11.#64        // java/lang/Exception.printStackTrace:()V
        #13 = Class              #65            // java/lang/String
        #14 = Methodref          #17.#66        // com/atguigu/java/MethodInnerStrucTest.compareTo:(Ljava/lang/String;)I
        #15 = String             #67            // 测试方法的内部结构
        #16 = Fieldref           #17.#68        // com/atguigu/java/MethodInnerStrucTest.str:Ljava/lang/String;
        #17 = Class              #69            // com/atguigu/java/MethodInnerStrucTest
        #18 = Class              #70            // java/lang/Object
        #19 = Class              #71            // java/lang/Comparable
        #20 = Class              #72            // 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               LocalVariableTable
        #30 = Utf8               this
        #31 = Utf8               Lcom/atguigu/java/MethodInnerStrucTest;
        #32 = Utf8               test1
        #33 = Utf8               count
        #34 = Utf8               test2
        #35 = Utf8               (I)I
        #36 = Utf8               value
        #37 = Utf8               e
        #38 = Utf8               Ljava/lang/Exception;
        #39 = Utf8               cal
        #40 = Utf8               result
        #41 = Utf8               StackMapTable
        #42 = Class              #63            // java/lang/Exception
        #43 = Utf8               compareTo
        #44 = Utf8               (Ljava/lang/String;)I
        #45 = Utf8               o
        #46 = Utf8               (Ljava/lang/Object;)I
        #47 = Utf8               <clinit>
        #48 = Utf8               Signature
        #49 = Utf8               Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
        #50 = Utf8               SourceFile
        #51 = Utf8               MethodInnerStrucTest.java
        #52 = NameAndType        #25:#26        // "<init>":()V
        #53 = NameAndType        #21:#22        // num:I
        #54 = Class              #73            // java/lang/System
        #55 = NameAndType        #74:#75        // out:Ljava/io/PrintStream;
        #56 = Utf8               java/lang/StringBuilder
        #57 = Utf8               count =
        #58 = NameAndType        #76:#77        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        #59 = NameAndType        #76:#78        // append:(I)Ljava/lang/StringBuilder;
        #60 = NameAndType        #79:#80        // toString:()Ljava/lang/String;
        #61 = Class              #81            // java/io/PrintStream
        #62 = NameAndType        #82:#83        // println:(Ljava/lang/String;)V
        #63 = Utf8               java/lang/Exception
        #64 = NameAndType        #84:#26        // printStackTrace:()V
        #65 = Utf8               java/lang/String
        #66 = NameAndType        #43:#44        // compareTo:(Ljava/lang/String;)I
        #67 = Utf8               测试方法的内部结构
        #68 = NameAndType        #23:#24        // str:Ljava/lang/String;
        #69 = Utf8               com/atguigu/java/MethodInnerStrucTest
        #70 = Utf8               java/lang/Object
        #71 = Utf8               java/lang/Comparable
        #72 = Utf8               java/io/Serializable
        #73 = Utf8               java/lang/System
        #74 = Utf8               out
        #75 = Utf8               Ljava/io/PrintStream;
        #76 = Utf8               append
        #77 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
        #78 = Utf8               (I)Ljava/lang/StringBuilder;
        #79 = Utf8               toString
        #80 = Utf8               ()Ljava/lang/String;
        #81 = Utf8               java/io/PrintStream
        #82 = Utf8               println
        #83 = Utf8               (Ljava/lang/String;)V
        #84 = Utf8               printStackTrace
      {
          //域信息
        public int num;
          descriptor: I
          flags: ACC_PUBLIC
    
        private static java.lang.String str;
          descriptor: Ljava/lang/String;
          flags: ACC_PRIVATE, ACC_STATIC
         //方法信息,这里是默认构造器(字节码角度也是方法)
        public com.atguigu.java.MethodInnerStrucTest();
          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 8: 0
              line 10: 4
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0      11     0  this   Lcom/atguigu/java/MethodInnerStrucTest;
    
        public void test1();
         //V 方法返回为void
          descriptor: ()V
          //访问权限
          flags: ACC_PUBLIC
          Code:
           //回顾栈篇章:栈深度3;局部变量表2;参数大小1 this
            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 16: 0
              line 17: 3
              line 18: 28
              //局部变量表
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0      29     0  this   Lcom/atguigu/java/MethodInnerStrucTest;
                  3      26     1 count   I
    
        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
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  5       4     2 value   I
                 13       4     2     e   Ljava/lang/Exception;
                  0      19     0   cal   I
                  2      17     1 result   I
            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
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       2     0  this   Lcom/atguigu/java/MethodInnerStrucTest;
                  0       2     1     o   Ljava/lang/String;
    
        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 8: 0
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                  0       9     0  this   Lcom/atguigu/java/MethodInnerStrucTest;
    
        static {};
          descriptor: ()V
          flags: ACC_STATIC
          Code:
            stack=1, locals=0, args_size=0
               0: ldc           #15                 // String 测试方法的内部结构
               2: putstatic     #16                 // Field str:Ljava/lang/String;
               5: return
            LineNumberTable:
              line 11: 0
      }
      Signature: #49                          // Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
      SourceFile: "MethodInnerStrucTest.java"
    Copy the code

conclusion

  • A valid bytecode file contains information about the version, fields, methods, and interfaces of the class, as well as information about the Constant Pool Table, including various literals and symbolic references.

  • The class file contains type information, domain information, method information (stack depth, local variable table, exception table, etc.) and other information. The information is loaded into the method area through the class loading subsystem (described in the previous chapter). Structure method area.

In the Class file structure, the first four bytes store the Magic Number, which determines whether a file is acceptable to the JVM, the next four bytes store the version Number, the first two bytes store the minor version Number, the last two store the major version Number, and then the constant pool for constants. The constant pool is mainly used to store two types of constants: literals and symbolic references. Literals are equivalent to the concept of Java language constants, such as text strings and constant values declared as final. Symbolic references belong to the concept of compilation principles.

Constant pool

Constant pool, also called Class constant pool (constant pool ==Class constant pool). A Java file is compiled into a Class file. In addition to describing the version, fields, methods, and interfaces of the Class, a Class file also contains a Constant pool. The Constant pool refers to the literal and symbolic references of the Class file stored in the method area after the Class file is loaded by the Java virtual Machine.

Features:

  • The constant pool is part of the class file
  • This is used to store the various literals and symbolic references generated at compile time, which are stored in the run-time constant pool in the method area after class loading.
    • Literals (string constants) :
      • Like a text string
      • Constant values declared as final
      • Values of basic data types, etc
    • Symbolic references:
      • Complete qualified name reference for classes and structures
      • Field names and descriptors
      • Method name and descriptor
  • The constant pool, which can be thought of as a table, is used by the virtual machine directive to find the class name, method name, parameter type, literal, and so on to execute.

  1. Why do we need constant pools

A Java source file that compiles to produce a bytecode file. In Java, bytecode requires data, which is often too large to be stored directly in the bytecode. Alternatively, it can be stored in the constant pool. The bytecode contains references to the constant pool. Runtime constant pools are used for dynamic linking, as described earlier.

For example:

public class simpleClass { public void sayHel1o() { System.out. println("hello"); }}Copy the code

It’s only 514 bytes, but it uses String, System, PrintStream, and 0bject. This is actually a very small amount of code. If there is more code, there will be more structures to refer to! This is where constant pools are needed! By decomposing the different constants. Regrouping as needed can greatly reduce the amount of code stored in the method area

Benefits of constant pools:

Constant pool is to avoid the frequent creation and destruction of objects and affect the system performance, it implements object sharing. The string constant pool, for example, puts all string literals into a constant pool at compile time.

  • Memory saving: All the same string constants in the constant pool are combined to occupy only one space.

  • Runtime savings: when comparing strings, == is faster than equals(). For two reference variables, only == is used to determine whether the references are equal, and therefore whether the actual values are equal.

Runtime constant pool

When a Class file is loaded into memory, the Java virtual machine transfers the contents of the Class file constant pool to the runtime constant pool (which is also one for each Class), and the strings from the Class file to the string constant pool. The Java language does not require constants to be generated only at compile time. That is, contents of the constant pool that are not pre-loaded into the Class file can enter the method area runtime constant pool. New constants may also be put into the pool during run time

  • The Runtime Constant Pool is part of the method area.
  • Run-time constant pools, which are created when classes and interfaces are loaded to the VIRTUAL machine.
  • The runtime constant pool is also one per class. Data items in the pool are accessed by index, just like array items.
  • The run-time constant pool contains a variety of constants, including numeric literals that are explicit at compile time and method or field references that are not available until run-time resolution. So instead of being the symbol address in the constant pool, this is going to beReal address (direct reference)
  • Another important feature of run-time constant pools relative to Class file constant pools is:DynamicThe Java language does not require that constants be generated only at compile time. That is, contents of the constant pool that are not pre-loaded into the CLass file can enter the method area runtime constant pool. New constants can also be put into the pool during run time.
    • String. intern()
  • The run-time constant pool is similar to a symbol table in a traditional programming language, but it contains richer data than a symbol table.
  • When creating a run-time constant pool for a class or interface, the JVM throws an OutOfMemoryError exception if the amount of memory required to construct the run-time constant pool exceeds the maximum that can be provided by the method area.

String constant pool

String constant Pool is also called String Pool, global String Pool, also called String Pool or String Table in English. At work, the String class is one of the object types we use very frequently. The JVM maintains a special memory space in order to improve performance and reduce memory overhead by avoiding the repeated creation of strings. The String constant pool is maintained privately by the String class.

Three pools relationship

When a class is executed by the JVM, it must be loaded, connected, and initialized, and the connection includes validation, preparation, and parsing. The constant pool is used to hold the various literal and symbolic references generated at compile time, but once the class is loaded into memory, the JVM stores the contents of the constant pool into the runtime constant pool, and string constants reside in the string constant pool in the heap.

Constant pool: A pool of constants defined in the class file

Runtime constant pool: The constant pool defined in the class file is loaded into the virtual organization as the runtime constant pool. Consists of literals and conforming references. Each class corresponds to a pool of runtime constants.

String constant pool (StringTable) : a pool of constants dedicated to storing strings. A string constant pool holds either a reference to a string or a string (both). The JVM has only one and shares it.

Note: The string. intern method returns the canonical representation of the String object. What it does is: first it checks whether the string exists in the constant pool. If it does, it returns the string in the constant pool (the reference address). If it does not, it adds the string to the constant pool first and returns the reference address

A chapter on string constant pool will be given in detail later!!

Method area garbage collection

Some people think that method areas (such as the meta space or permanent generation in a HotSpot virtual machine) are not garbage collected, but they are not. The Java Virtual Machine Specification is very lenient on the method area and mentions that it is possible to not require the VIRTUAL machine to implement garbage collection in the method area. In fact, there are collectors that do not implement or do not fully implement method area type unloading (for example, the zGc collector from JDK 11 did 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. But recycling in this area is sometimes necessary. Some of the most serious bugs in Sun’s previous Bug list were memory leaks caused by older versions of HotSpot virtual machines not fully reclaiming this area.

The method area garbage collection mainly reclaims two parts: discarded constants in the constant pool and types that are no longer used.

The “useless class” decision condition

  1. All instances of this class have been reclaimed

  2. The class load that loaded the class has been reclaimed (this condition is usually difficult to achieve unless it is a well-designed alternative class loader scenario, such as OSGi, JSP reloading, etc.).

  3. The java.lang.Class object corresponding to this Class does not have any peer reference, and the methods of this Class cannot be accessed anywhere through reflection.

The Java virtual Machine is allowed to reclaim useless classes that meet all three of the above conditions, but I’m just saying “allowed”, not that there’s no reference to an object. The HotSpot virtual machine provides the -xNoClassGC parameter to control whether or not to recycle the type, You can also use -verbose:class, -xx :+ traceclass-loading, and -xx :+ traceclassassloading to view class Loading and unloading information

In scenarios where bytecode frameworks such as reflection, dynamic proxy, CGLib, dynamic generation of JSPS, and frequent custom class loaders such as OSGi are used extensively, the ability to type unload in the Java Virtual Machine is often required to ensure that the method area is not overburdened with memory.

Class

  • Classes loaded by the class loader of the Java VIRTUAL Machine are not unloaded during the life cycle of the VM.
  • The Java virtual Machine itself will always refer to these Class loaders, and these Class loaders will always refer to the Class objects of the classes they load, so these Class objects will always be accessible. Classes loaded by user-defined class loaders can be unloaded.
  • The HotSpot virtual machine has a clear recycling policy for constant pools, as long as the constants in the constant pool are not referenced anywhere, they can be reclaimed.
  • Reclaiming discarded constants is very similar to reclaiming objects in the Java heap.