The interaction between heap, stack and method area
2. 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 expandable
- 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 space or Java. Lang, OutOfMemoryError: Metaspace, such as:
- Load a large number of third-party JAR packages;
- Too many Tomcat projects are deployed.
- A large number of dynamically generated reflection classes;
- Shutting down the JVM frees up memory in this area.
1. Method area evolution in the HotSpot VIRTUAL machine
- 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 it seems that the use of permanent generation is not a good idea. Causes Java programs to be easier to OOM(exceeding -xx :MaxPermSize limit).
Implementation of method area in JDK7 and JDK8:
In JDK8, the concept of permanent generations has finally been scrapped completely and replaced with 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 in the local memory (PC memory).
- It’s not just the names of the permanent generations and metacases that have changed. The internal structure has also been adjusted.
- According to the Java Virtual Machine Specification, if the method area cannot meet the new memory allocation requirements, an OOM exception is raised.
3. Set parameters of method area size
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.
1. Jdk7 and before (permanent generation) :
- -xx: PermSize sets the initial space allocation for the permanent generation. The default value is 20.75 MB
- -xx: MaxPermSize Sets the maximum space that can be allocated for the permanent generation. The default is 64M for 32-bit machines and 82M for 64-bit machine mode
- When the number of classes loaded by the JVM exceeds this value, OutOfMemoryError: PermGen Space is raised
2. Jdk8 and later (meta space) :
- The metadata area size can be specified using -xx: MetaspaceSize and -xx: MaxMetaspaceSize instead of the previous two parameters.
- The default values are platform dependent. On Windows, the value of -xx: MetaspaceSize is 21M, and the value of -xx: MaxMetaspaceSize is -1, indicating that 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 also throws OutOfMemoryError: Metaspace.
- -xx: MetaspaceSize: sets the initial MetaspaceSize size. For a 64-bit server-side JVM, the default -xx: MetaspaceSize value is 21MB. 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, increase this value appropriately until MaxMetaspaceSize is exceeded. If too much space is freed, lower this value appropriately.
- If the initial high water mark is set too low, the high water mark adjustment described above may 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 to set -xx: MetaspaceSize to a relatively high value.
OOM: (Memory leakage or overflow) :
- 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. In other words, you need to distinguish between a Memory Leak and a Memory 0verflow.
- If there is a memory leak, you can further use the tool to see the reference chain of the leaking object to GC Roots (an idle object in the heap cannot be reclaimed due to the reference chain, even though it is already an idle resource). 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 GC Roots 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 (-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.
4. Internal structure of method area
In understanding the Java VIRTUAL Machine, the method area store is described as follows: It is used to store type information that has been loaded by the virtual machine, constants, static variables, and code cache compiled by the just-in-time compiler.
1. Type information
For each loaded type (class, interface, enum, annotation), the JVM must. The following types of information must be stored in the method area:
- The full valid name for this type (full name = package name. 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
2. Domain information (member variables)
- 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).
3. Method Information
The JVM must hold the following information about all methods, including the declaration order, as well as domain information:
- Method name.
- Method return type (or void).
- The number and type of method arguments (in order).
- Method modifiers (a subset of public, private, protected, static, final, synchronized, native, abstract).
- Methods bytecodes, operand stack, local variable table and size (except abstract and native methods).
- Exception table (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.
4. Non-final class variables (static variables that are not declared final)
- 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 if there is no instance of the class.
The following code does not report a null pointer exception:
public class MethodAreaTest {
public static void main(String[] args) {
Order order = null; order.hello(); System.out.println(order.count); }}class Order {
public static int count = 1;
public static final int number = 2;
public static void hello(a) {
System.out.println("hello!"); }}Copy the code
5. Static final
Class variables declared final are handled differently, with each global constant assigned at compile time.
Order. Class bytecode file, right click Open in Terminal, Javap -v -p order.class > tst.txt decompile the bytecode file into a TXT file. You can see that the constant number declared static final is assigned at compile time. This is unlike the static variable count, which is not modified by final, which is assigned in preparation for class loading (remember Clinit).
public static int count;
descriptor: I
flags: ACC_PUBLIC, ACC_STATIC
public static final int number;
descriptor: I
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: int 2
Copy the code
Constant pool
- A valid bytecode file contains the Constant Poo1 Table, which contains literals and symbolic references to type fields and methods, in addition to the version information, fields, methods, and interface descriptions of the class.
- A Java source file of classes, interfaces, compiled to produce a bytecode file. Bytecodes in Java require data, usually too large to be stored directly in bytecodes, or in a constant pool; This bytecode contains a reference to the constant pool. Runtime constant pools are used for dynamic linking.
For example, the following code, although only 194 bytes, uses string, System, Printstream, and Object structures. This is actually a pretty small amount of code. If you have more code, more structures are referenced!
Public class Simpleclass {
public void sayhelloo(a) {
System.out.Println (hello) }
}
Copy the code
Several types of data stored in a constant pool include:
- Number of values
- A string value
- Class reference
- Field reference
- Method references
Summary: The constant pool in bytecode is a table from which virtual machine instructions find the class names, method names, parameter types, literals, etc.
Run-time 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 a pool, like array items, are accessed by index.
- 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. So instead of having 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.
- String.intern()
- 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 the Symbol table in traditional programming languages, but it contains a bit more data than the 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 can be provided by the method area.
7. Evolution details of the method area
To be clear: only HotSpot has persistent generation. For BEA JRockit, IBM J9, etc., there is no concept of permanent generation. In principle, the implementation method area belongs to the implementation details of virtual machines and is not governed by the Java Virtual Machine Specification and does not require uniformity.
Changes to the method area in Hotspot:
- Jdk1.6 and before: Permanent Generation,Static variables are stored on the permanent generation.
- Jdk1.7: There are permanent generations,But it has been progressively “de-perpetuated”, removing the pool of string constants and static variables and storing them in the heap.
- Jdk1.8 and later: No permanent generation,Type information, fields, methods, and constants are kept in the local memory meta-space, but the string constant pool and static variables remain in the heap space.
1. What should be replaced by meta space for permanent proxies
- With the advent of Java8, persistent generations are no longer seen in HotSpot VM. But that doesn’t mean classes. The metadata information of the. 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 there are too many dynamically loaded classes, it is easy to produce O0M of the Perm area (permanent generation). For example, in a practical Web project, because there are many function points, many classes need to be dynamically loaded during operation, and fatal errors often occur. “The Exception in the thread ‘dubbo client 7.0.x.x connector’ Java lang. OutOfMemoryError: PermGenspace” and the biggest difference between space and permanent generation is: 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.
2. Why should StringTable be adjusted
- Jdk7 puts StringTable in heap space, correct.
- 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.
Eight, static variables, member variables, local variables storage location
/** * Where are 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
- StaticObj is stored in the method area along with the type information of Test, instance0bj 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 ().
hsdb>scanoops 0x00007f32c7800000 0x00007f32c7b50000 JHSDB_ _TestCase$Obj ectHolder
0x00007f32c7a7c458 JHSDB_ TestCase$Obj ectHolder
0x00007f32c7a7c480 JHSDB_ TestCase$Obj ectHolder
0x00007f32c7a7c490 JHSDB_ TestCase$Obj ectHolder
Copy the code
- 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.
- Then, I find a reference to the staticObj object in an instance of java.lang. Class, and I give the address of the instance. You can clearly see that this is indeed an instance of an object of type java.lang.Class, with an instance field named staticObj:
- According to the conceptual model defined in the Java Virtual Machine Specification, all C1ass information should be stored in the method area. However, the Java Virtual Machine Specification does not specify how the method area should be implemented, and this becomes a matter of flexibility for different virtual machines. JDK7 and later Hotspot virtual machines have chosen to store static variables and type mapping C1ass objects on the Java side of the language in the AVA heap, and this was clearly verified in our experiments
Garbage recycling in the method area
Some people think that method areas (such as Hotspot, meta-spaces in virtual machines, or persistent generations) 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 do not fully implement method area type offloading (for example, the 2GC collector in 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
1. Obsolete constants in the constant pool
- 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 are a compilation principle concept.
- There are three types of constants in the constant pool:
- 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.
2. A type that is no longer used in the constant pool
- 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 an Xnoclassgc parameter to control whether or not to reclaim a type. It can also use a verbose: class as well as a XX: +TraceClass Loading, a XX: Traceclassclass load and unload 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.
Ten,
Xi. Interview
Baidu: Three aspects: say about the JVM memory model, which areas? What are they?
Which regions of JVM memory are divided into, and what does each region 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
Xiaomi: JVM memory partition, why should there be new generation and old generation
Bytedance: Part 2: Java’s memory partitioning Part 2: When will objects become obsolete in the JVM runtime data repository?
JVMS 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?
One side: Jvm memory model and partition, need to be detailed to each partition what to put. One side: what changes have been made to the memory model of the JVM in Java8
Pinduoduo: How many partitions are there in the JVM, and what does each partition do?
Meituan: Does garbage collection happen in the permanent generation of the Java Memory allocation JVM? One side: The JVM memory partition, why the new generation and the old age?