Make writing a habit together! This is the second day of my participation in the “Gold Digging Day New Plan · April More text challenge”. Click here for more details.

Hello, everyone. I am a senior programmer, specializing in sharing big data, algorithms, Java, Python and other related knowledge. Welcome to exchange and learn with me. To contact me

Now that we’ve finished updating the JVM’s classloading subsystem and virtual machine stack, today we’ll talk about the METHODS section of the JVM.

First, let’s look at the interaction between the method area and the heap and stack.

  • Users are stored in a meta-space, or in a method area
  • The variable user is stored in a table of local variables in the Java stack
  • New User() is stored in the Java heap

Method area understanding

The Java Virtual Machine Specification makes it clear that “even though all method areas are logically part of the heap, some simple implementations may not choose to garbage collect or compress.” But for the HotSpot virtual machine, the method area is also called non-heap to separate it from the Heap.

So, the method area can be thought of as a piece of memory separate from the Java heap.

The method area mainly houses classes, while the heap mainly houses instantiated objects.

  • The method area, like the JAVA heap, is an area 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.
  • 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 the method area overflows, the virtual machine will also throw an out-of-memory error.
    1. Load a large number of third-party JAR packages
    2. Too many projects are deployed for Tomcat
    3. A number of dynamically generated reflection classes
  • Shutting down the JVM frees up this memory area

Method area evolution in HotSpot

Before JDK1.7, it was customary to call a method area a permanent generation. Starting with JDK1.8, permanent generations are replaced with meta-spaces. After JDK1.8, the meta space is stored in off-heap memory.

The Java Virtual Machine Specification does not have uniform requirements on how to implement the method area. For example, the concept of a persistent generation does not exist in IBM J9. Since JDK1.8, the HotSpot VIRTUAL machine has completely abandoned the concept of persistent generation, replacing it with a meta-space implemented in local memory as in J9.

Similar in nature to the persistent generation, meta-spaces are implementations of method areas in the virtual machine 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.

Set method area size to OOM

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.

Jdk7 and before:

  • The -xx :Permsize command is used to set the initial space allocation for the permanent generation. The default value is 20.75 MB.

  • Run the -xx :MaxPermsize command to set the maximum space that can be allocated for the permanent generation. The default value is 64M for 32-bit machines and 82M for 64-bit machines.

  • When the number of classes loaded by the JVM exceeds this value, OutOfMemoryError:PermGen Space is raised.

After jdk8:

The metadata size can be specified using the arguments -xx :MetaspaceSize and -xx :MaxMetaspaceSize. 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 also throws OutOfMemoryError: Metaspace.

-xx :MetaspceSize: sets the initial MetaspceSize size. For a 64-bit server-side JVM, the default value is 21M. This is the initial high watermark, and once it is reached, FullGC will trigger and unload useless classes (that is, their corresponding classloaders are no longer alive), and then 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, increase this value appropriately without exceeding MaxMetaspaceSize. If too much space is freed, lower the value appropriately.

If the initial high water level is set too low, the above high water level adjustment can occur many times. Multiple FullGC calls can be observed through the garbage collector logs. To avoid frequent GC, it is recommended to set -xx :MetaspaceSize to a relatively high value.

How to Solve OOM

In order to resolve OOM or Heap Space exceptions, the Eclipse Memory Analyzer is used to analyze the Heap dump snapshots first. The focus is to determine whether the objects in Memory are necessary. You have to figure out whether you’re leaking Memory or Overflow.

A memory leak is when a large number of references point to objects that will not be used in the future because they are associated with GC Roots, so these objects will not be collected in the future.

  • 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 leak objects are associated with GC Roots and cause the garbage collector to fail to reclaim them automatically. With the type information of the leaking object and the information of the GCRoots reference chain, the location of the leaking code can be more accurately located.

  • 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 (Xms and -xmx), 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.

The internal structure of the method area

The method area mainly stores the type information that has been loaded by the virtual machine, constants, static variables, and the code cache compiled by the just-in-time compiler.

The type information

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

  • The full valid name (full name: package name) for this type. The name of the class)
  • The full valid name of the type’s immediate parent (no parent for interface or java.lang.Object)
  • Modifiers of this type (some subset of public, Abstract, final)
  • An ordered list of direct interfaces of this type
Domain 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 (a subset of public, private, protected, static, final, volatile, and transiend)

Method information

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

  • Method names
  • Method return type (or void)
  • Number and type of method parameters (in order)
  • Method modifiers (public, private, protected, static, final, synchronized, native, abstrat)
  • Bytecodes, operand stack, local variable table and size of methods (except abstract and native methods)
  • Exception list (except for abstract and native methods)
Non-final class variable

Static variables are associated with the class, loaded as the class is loaded, and they become a logical part of the class data.

A class variable is shared by all instances of the class, and you can access it even when there are no instances of the class.

Public class MethodAreaTest {public static void main(String[] args) {Student Student =new Student(); student=null; student.hello(); System.out.println(student.gender); }} class Student{public static String name=" "; Public static final String gender=" male "; public static void hello(){ System.out.println("hello"); }}Copy the code

As shown in the code above, even if we set student to null, there will be no null pointer exception.

Global constants

Global constants are modified with static final, and each global constant is assigned at compile time.

Runtime constant pool VS constant pool

As the name implies, a runtime constant pool is a constant pool at runtime.

  • 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

A valid bytecode file contains not only the class version information, field, method, and interface descriptor information, 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.

The constant pool mainly includes:

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

In general, 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.

Run-time constant pool

The runtime constant pool is part of the method area. The constant pool table is the part of the Class file that holds the various literals and match references generated at compile time and is stored in the runtime constant pool in the method area after the Class is loaded.

The JVM maintains a constant pool for each loaded type (class or interface). Data items in a pool, like array items, are accessed by index.

The runtime constant pool contains a variety of constants, ranging from numeric literals that are explicit at compile time to method and field references that are not available until runtime parsing. Now instead of a symbolic address in the constant pool, we have a real address.

Another important feature of run-time constant pools as opposed to Class file constant pools is that they are dynamic.

A run-time constant pool is similar to a symbol table in a traditional programming language, but it contains a bit more data than a symbol table.

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 the method area can provide.

The evolution of the HotSpot VIRTUAL machine method area

  • Jdk1.6 and earlier: there are permanent generations on which static variables are stored.
  • Jdk1.7: there are permanent generations, but it is moving away from “permanent generations”, string constant pools, static variables stored in the heap.
  • Jdk1.8: No persistent generation, type information, fields, methods, constants are stored in the local memory meta-space, but the string constant pool, static variables are stored in the heap.
Why does a string constant pool adjust its position

In JDK 1.7, the string constant pool is placed in the heap space. Because the collection efficiency of the permanent generation is low, it is triggered during full GC. The full GC is triggered only when the old generation space is insufficient or the permanent generation space is insufficient. As a result, the collection efficiency of StringTable is not high. 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. And when you put it in the heap, you can recycle it more quickly.

Where are static variables stored

The object entity corresponding to a static reference always exists in the heap space.

Method area garbage collection

Some people think method districts are garbage – free, but they are not. 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.

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. In the past, there were several serious bugs on Sun’s bug list that were caused by memory leaks caused by earlier versions of HotSpot VMS 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.

First, there are two main types of constants stored in the constant pool in the method area: 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. (The collection of constants is relatively simple, focusing on the collection of classes).

Determining whether a constant is “obsolete” is relatively easy, while determining whether a type is an “out-of-use class” is 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 is already recycled, a condition that is difficult to achieve unless there are carefully designed scenarios that can replace the classloader, such as OSGI, JSP reloads, 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. 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 heavily used, dynamically generated JSPS, and frequently custom classloaders such as OSGI, the ability to type unload is often required to ensure that the Java VIRTUAL machine does not overburden the method area with memory.

The last

So far, we will finish the JVM method area, if you feel good, forward, view, like arrangement.

The more you know, the more you open your mind. I’ll see you next time.