Note source: Silicon Valley JVM complete tutorial, millions of playback, the peak of the entire network (Song Hongkang details Java virtual machine)

Update: gitee.com/vectorx/NOT…

Codechina.csdn.net/qq_35925558…

Github.com/uxiahnan/NO…

[TOC]

7. Method of area

In terms of thread sharing or not

7.1. Interaction between stack, heap and method area

7.2. Understanding of the method area

The Structure of The Java Virtual Machine (Oracle.com)

7.2.1. Where is 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.” But in the case of HotSpotJVM, the method area is also called non-heap to separate it from the Heap.

So, the method area is considered a piece of memory separate from the Java heap.

7.2.2. Basic understanding of method area

  • The Method Area, like the Java heap, is an Area of memory shared by individual threads.
  • The method area is created at JVM startup, and its actual physical memory space can be as discontinuous as the Java heap area.
  • The size of the method area, like the heap space, can be fixed or scalable.
  • The size of the method area determines how many classes the system can hold. If the system defines too many classes and causes the method area to overflow, the VIRTUAL machine will also throw an overflow error:java.lang.OutOfMemoryError: PermGen spaceorjava.lang.OutOfMemoryError: Metaspace
    • Loading a large number of third-party JAR packages; Too many Tomcat projects (30 to 50) are deployed. Lots of dynamically generated reflection classes
  • Shutting down the JVM frees up memory in this area.

7.2.3. Method area evolution in HotSpot

In JDK7 and before, it was customary to call a method area a permanent generation. Starting with JDK8, permanent generations are replaced with meta-spaces.

In essence, method blocks and permanent generations are not equivalent. Only for Hotspot. The Java Virtual Machine Specification does not have uniform requirements on how to implement the method area. For example: BEA JRockit/IBM J9 does not have the concept of a permanent generation.

Now, the use of permanent generation is not a good idea. Causes Java programs to be easier OOM (exceeding -xx :MaxPermsize limit)

However, in JDK8, the concept of permanent generation is completely abandoned and replaced by Metaspace, which is implemented in local memory like JRockit and J9

Similar in nature to permanent generations, meta-spaces 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 VM, but uses local memory

It’s not just the names of the permanent generation and the metacolor that have changed

According to the Java Virtual Machine Specification, if the method area cannot meet the new memory allocation requirements, an OOM exception is raised

7.3. Set method area size to OOM

7.3.1. Setting the size of method area memory

The size of the method area does not have to be fixed, and the JVM can adjust it dynamically based on the needs of the application.

Before jdk7 and

  • through-XX:PermsizeTo set the initial allocation of the permanent generation. The default value is 20.75 MB
  • through-XX:MaxPermsizeTo set the maximum allocatable space of the permanent generation. The default is 64M for 32-bit machines and 82M for 64-bit machine mode
  • When the JVM loads more class information than this value, an exception is reportedOutOfMemoryError:PermGen space.

After JDK8

  • Metadata area size can use parameters-XX:MetaspaceSize-XX:MaxMetaspaceSizeThe specified
  • The default values are platform dependent. Under Windows,-xx :MetaspaceSize=21M -xx :MaxMetaspaceSize=-1// There is no limit.
  • Unlike the permanent generation, if the size is not specified, the virtual machine uses up all available system memory by default. If the metadata area overflows, the VM will also throw an exceptionOutOfMemoryError:Metaspace
  • -XX:MetaspaceSize: Sets the initial size of the meta-space. The default for a 64-bit server-side JVM-XX:MetaspaceSizeValue is 21 MB. This is the initial high watermark, and once it is reached, the Full GC will be triggered to unload useless classes (that is, their corresponding classloaders are no longer alive), and the high watermark will reset. The value of the new high water level depends on how much space is freed after GC. If the free space is insufficient, then in no more thanMaxMetaspaceSize, appropriately increase the value. If too much space is freed, lower this value appropriately.
  • If the initial high water mark is set too low, the above high water mark adjustment can occur many times. Multiple calls to the Full GC can be observed from the garbage collector’s logs. To avoid frequent GC, it is recommended that-XX:MetaspaceSizeSet to a relatively high value.

Example 1: An example of Understanding the Java Virtual Machine

For example 2

/** * jdk8中 : * -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 the binary bytecode of the class
                ClassWriter classWriter = new ClassWriter(0);
                // Specify the version number, public, class name, package name, parent class, interface
                classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "Class" + i, nu1l, "java/lang/Object".null);
                / / return byte []
                byte[] code = classWriter.toByteArray();
                // Class loading
                test.defineClass("Class" + i, code, 0, code.length); / / CLass objectj++; }}finally{ System.out.println(j); }}}Copy the code

7.3.2. How to solve these OOM

  1. To resolve OOM or Heap space exceptions, a common method is to first analyze heap dump snapshots through a Memory image analysis tool (such as Eclipse Memory Analyzer). The focus is to determine whether the objects in Memory are necessary. If you have a Memory Leak or a Memory Overflow, you need to know the difference between a Leak and a Memory Overflow.

  2. If it is a memory leak, you can further look at the leak object’s chain of references to GC Roots through the tool. You can then find out how the leaking objects are associated with GCRoots and cause the garbage collector to fail to reclaim them automatically. With the information of the type of the leaking object and the information of the GCRoots reference chain, the location of the leaking code can be more accurately located.

  3. If there is no memory leaks, in other words, an in-memory object does also have to live with, it shall check the pile of parameters of the virtual machine (-xmx and – Xms), compared with the machine physical memory to see if can also big, check whether there is a certain object lifecycle from the code is too long, the state holding time is too long, Try to reduce the memory consumption of the program’s runtime.

7.4. Internal structure of the method area

7.4.1. What is stored in the Method Area?

The Method Area storage content in Understanding the Java VIRTUAL Machine is described as follows:

It is used to store type information that has been loaded by the virtual machine, constants, static variables, just-in-time compiler compiled code caches, and so on.

7.4.2. Internal structure of the method area

The type information

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

  1. The full valid name for this type (full name = package name. The name of the class)
  2. The full valid name of the type’s immediate parent (no parent for interface or java.lang.object)
  3. Modifiers of this type (some subset of public, abstract, final)
  4. An ordered list of direct interfaces of this type

Field information

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

Domain information includes domain name, domain type, and domain modifiers (public, private, protected, static, final, volatile, transient).

Method information

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

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

Non-final class variable

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

Static final static final

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

7.4.3. Runtime constant pools VS constant pools

  • Method area, which contains the run-time constant pool
  • A bytecode file that contains a constant pool
  • To understand the method area, you need to understand the ClassFile, because the information for loading classes is in the method area.
  • To understand the runtime constant pool in the method area, you need to understand the constant pool in ClassFile.

The official document: docs.oracle.com/javase/spec…

A valid bytecode file contains not only the class version information, fields, methods, and interface descriptors, but also the Constant Pool Table, which contains various literals and symbolic references to types, fields, and methods

Why do WE need constant pools?

A Java source file of classes, interfaces, compiled to produce a bytecode file. Bytecodes in Java require data support, usually too large to be stored directly in bytecodes, or, alternatively, in a constant pool, which contains references to the constant pool. Runtime constant pools are used for dynamic linking, as described earlier.

For example:

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

It’s only 194 bytes, but it uses structures like String, System, PrintStream, and Object. The amount of code here is actually very small, if there is more code, the reference structure will be more, and this is where the constant pool is needed.

What’s in the constant pool?

The types of data stored in the hit constant pool include:

  • Number of values
  • A string value
  • Class reference
  • Field reference
  • Method references

For example, the following code:

public class MethodAreaTest2 {
    public static void main(String args[]) {
        Object obj = newObject(); }}Copy the code

Object obj = new Object(); Will be translated into the following bytecode:

0: new #2  // Class java/lang/Object
1: dup
2: invokespecial // Method java/lang/Object "<init>"() V
Copy the code

summary

A constant pool can be thought of as a table from which virtual machine instructions find the class names, method names, parameter types, literals, and so on to execute

7.4.4. Runtime constant pools

  • The Runtime Constant Pool is part of the method area.
  • The Constant Pool Table is the part of the Class file that stores literal and symbolic references generated at compile time and is stored in the runtime Constant Pool in the method area after the Class is loaded.
  • Runtime constant pool, which is created after classes and interfaces are loaded into the VIRTUAL machine.
  • The JVM maintains a constant pool for each loaded type (class or interface). Data items in the pool, like array items, are passedIndex access.
  • The runtime constant pool contains a variety of constants, from numeric literals that are explicit at compile time to method or field references that are not available until they are parsed at run time. Now instead of the symbolic address in the constant pool, I’m going to change it toThe real address.
  • Another important feature of run-time constant pools over Class file constant pools is that they are availabledynamic.
  • The runtime constant pool is similar to the symboltable in traditional programming languages, but it contains a bit more data than the symboltable.
  • When creating a runtime constant pool for a class or interface, the JVM throws an OutOfMemoryError if the amount of memory required to construct the runtime constant pool exceeds the maximum that can be provided by the method area.

7.5. Method Area Usage Examples

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

7.6. Evolution details of the method area

  1. To be clear: only Hotspot has persistent generation. For BEA JRockit, IBMJ9, etc., there is no concept of permanent generation. In principle, how to implement the method area is a virtual machine implementation detail that is not governed by the Java Virtual Machine Specification and does not require unification
  2. Changes to the method area in Hotspot:
JDK1.6 and before There are permanets, where static variables are stored
JDK1.7 There are permanent generations, but have been progressively “de-permanent”, string constant pools, static variables removed, and stored in the heap
JDK1.8 No persistent generation, type information, fields, methods, and constants are stored in the local memory meta-space, but the string constant pool, static variables are still in the heap.

7.6.1. Why are permanent generations replaced by meta-spaces?

JEP 122: Remove the Permanent Generation (java.net)

JRockit is a fusion with HotSpot, because JRockit doesn’t have persistent generation, so they don’t need to configure persistent generation

With the advent of Java8, persistent generations are no longer seen in HotSpot VM. But this does not mean that the metadata information of the class has disappeared. This data is moved to an area of local memory not connected to the heap, called Metaspace.

Since the metadata of a class is allocated in local memory, the maximum allocatable space of the metadata space is the memory space available to the system.

This change was necessary for the following reasons:

  • Setting the size of the space for the permanent generation is difficult to determine. In some scenarios, if too many classes are dynamically loaded, oom in the Perm area may be generated. For example, in a real Web process, because there are many function points, many classes need to be dynamically loaded during operation, and fatal errors often occur.

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

    The biggest difference between a meta-space and a permanent generation is that the meta-space is not in the virtual machine, but uses local memory. Therefore, by default, the size of the meta-space is limited only by local memory.

  • Tuning persistent generations is difficult.

Some people think that method areas (such as meta-spaces or persistent generations in the HotSpot VIRTUAL machine) have no garbage collection behavior, but this is not true. The Java Virtual Machine Specification is very relaxed about method areas, mentioning that virtual machines are not required to implement garbage collection in method areas. Collectors do exist that do not implement or do not fully implement method area type offloading (for example, the ZGC collector in JDK 11 did not support class offloading). Generally speaking, the recovery effect of this area is not satisfactory, especially for the type of unloading, the conditions are quite harsh. But recycling in this area is sometimes necessary. Several of the most serious bugs on Sun’s previous Bug list were memory leaks caused by earlier versions of the HotSpot VIRTUAL machine not fully reclaiming this area

The method area garbage collection collects two main parts: obsolete constants in the constant pool and types that are no longer used

7.6.2. Why does StringTable Reposition?

Jdk7 puts StringTable in the heap space. Because the collection efficiency of the permanent generation is low, it is triggered during full GC. Full GC is triggered when the old generation runs out of space and the permanent generation runs out.

This results in inefficient StringTable recycling. However, in our development, a large number of strings will be created, and the recycling efficiency is low, resulting in insufficient memory of permanent generation. Put it in the heap, it can recycle memory in time.

7.6.3. Where are static variables stored?

/** * static references to object entities always exist in heap space * jdk7: * -Xms200m -Xmx200m -XX:PermSize=300m -XX:MaxPermSize=300m -XX:+PrintGCDetails * jdk8: * -Xms200m -Xmx200m-XX:MetaspaceSize=300m -XX:MaxMetaspaceSize=300m -XX:+PrintGCDetails */
public class StaticFieldTest {
    private static byte[] arr = new byte[1024 * 1024 * 100];
    public static void main(String[] args) {
        System.out.println(StaticFieldTest.arr);
        
        try {
            Thread.sleep(1000000);
        } catch(InterruptedException e){ e.printStackTrace(); }}}Copy the code
/** * Where is staticobj, instanceobj, Localobj stored? * /public class StaticobjTest {    static class Test {        static ObjectHolder staticobj = new ObjectHolder();        ObjectHolder instanceobj = new ObjectHolder();        void foo(a){            ObjectHolder localobj = new ObjectHolder();            System.out.println("done"); }}private static class ObjectHolder{        public static void main(String[] args) {            Test test = newStaticobjTest.Test(); test.foo(); }}}Copy the code

JHSDB tool was used for analysis, details omitted here

Staticobj is stored in the method area along with the type information of Test, Instanceobj is stored in the Java heap along with the object instance of Test, and LocalObject is stored in the local variation table of the stack frame of foo().

The test found that the addresses of the data in memory of the three objects were all in the Eden area, so the conclusion was that the object instances would be allocated in the Java heap.

The staticobj object is found in an instance of java.lang.Class, and the address of the instance is given. Checking the instance in the Inspector, it is clear that this is indeed an instance of java.lang.Class. There is an instance field called Staticobj:

According to the conceptual model defined in the Java Virtual Machine Specification, all class-related information should be stored in the method area. However, the Java Virtual Machine Specification does not specify how the method area should be implemented, leaving it a matter of flexibility for different virtual machines. The JDK7 and later HotSpot virtual machines have chosen to store class objects that map static variables and types on the Java side of the language together in the Java heap, and this was clearly verified in our experiments

7.7. Method area garbage collection

Some people think that method areas (such as meta-spaces or persistent generations in the Hotspot VIRTUAL machine) have no garbage collection behavior, but this is not true. The Java Virtual Machine Specification is very relaxed about method areas, mentioning that virtual machines are not required to implement garbage collection in method areas. In fact, collectors do exist that do not implement or fully implement method area type offloading (for example, the zGC collector of the JDK11 era did not support class offloading).

Generally speaking, the recovery effect of this area is not satisfactory, especially for the type of unloading, the conditions are quite harsh. But recycling in this area is sometimes necessary. Several of the most serious bugs on Sun’s previous Bug list were memory leaks caused by earlier versions of the HotSpot VIRTUAL machine not fully reclaiming this area.

The method area garbage collection collects two main parts: obsolete constants in the constant pool and types that are no longer used.

Let’s start with the two main types of constants stored in the method area constant pool: literals and symbolic references. Literals are close to the Java language level concepts of constants, such as text strings, constant values declared final, and so on. Symbolic references, on the other hand, are concepts related to compilation principles and include the following three constants:

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

The HotSpot VIRTUAL machine has a very clear policy for reclaiming constants from the constant pool as long as they are not referenced anywhere.

Recycling deprecated constants is very similar to recycling objects in the Java heap.

It is relatively easy to determine whether a constant is “obsolete,” while the criteria for determining whether a type is “no longer in use” are more demanding. The following three conditions must be met simultaneously:

  • All instances of the class are already recycled, that is, there are no instances of the class or any of its derived children in the Java heap.

  • The classloader that loaded the class has already been recycled, a condition that is usually difficult to achieve unless it is a carefully designed alternative classloader scenario, such as OSGi, JSP reloading, and so on.

  • The java.lang.Class object corresponding to this Class is not referenced anywhere, and the methods of this Class cannot be accessed anywhere through reflection.

The Java virtual machine (JVM) is allowed to recycle useless classes that meet the above three criteria, only “allowed”, not necessarily recycled as objects do when they are no longer referenced. The HotSpot virtual machine provides the -xnoClassGC parameter to control whether or not to reclaim the type, You can also use -verbose:class and -xx :+TraceClassLoading and -xx :+TraceClassLoading to view class loading and unloading information

In scenarios where bytecode frameworks such as reflection, dynamic proxies, and CGLib are used extensively, JSPS are dynamically generated, and custom class loaders such as OSGi are frequently used, the Ability of the Java VIRTUAL machine to type unload is often required to ensure that the method area is not overloaded with memory.

conclusion

Frequently seen exam

Baidu:

What are the areas of the JVM memory model? What are they?

Ant Financial:

How many partitions are there in the JVM memory, and what does each partition do?

One side: JVM memory distribution/memory structure? What’s the difference between stack and heap? The structure of the heap? Why two survivor zones?

Side TWO: Eden and Survior proportional allocation

Millet:

JVM memory partition, why have new generation and old generation

Bytedance:

Second side: Java memory partition

Part 2: When will objects become obsolete in the VM runtime data repository?

Jingdong:

JVM memory structure, Eden and Survivor ratio.

JVM memory is divided into new generation, old generation, persistent generation.

Why should the new generation be divided into Eden and survivor?

Tmall:

One side: THE Jvm memory model and partitions need to be detailed to what is placed in each partition.

One side: what changes did Java8 make to the memory model of the JVM

Spelling is great:

How many partitions are there in the JVM memory, and what does each partition do?

Meituan:

Java Memory allocation Does garbage collection occur in the permanent generation of the JVM?

One side: The JVM memory partition, why the new generation and the old age?