Complete JVM learning notes please click here
1. Interaction between heap, stack and method area
Run-time data area structure diagram
The interaction between heap, stack, and method areas
2. Understanding of method area
The Java Virtual Machine Specification makes it clear: ‘Although all method areas are logically part of the heap, some simple implementations may not choose to garbage collect or compress. ‘But for HotSpotJVM, a method area is also called a 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, 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 examples for this region and uses JVisualVM to see how many classes are loaded
public class MethodAreaDemo {
public static void main(String[] args) {
System.out.println("start...");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end..."); }}Copy the code
- 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 OOM(exceeding -xx :MaxPermSize limit)
Method area in JDK7 and JDK8 implementation
-
In JDK8, the concept of permanent generations has finally been scrapped completely and replaced with Metaspace, which is implemented in local memory as in 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 the local 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 the size of the method area 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:
- A XX: PermSize is used to set the initial allocation of permanent generation space. 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
Jdk8 and later:
- 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. In Windows, the value of an XX: MetaspaceSize is 21 MB, and the value of an XX: MaxMetaspaceSize is 1. | I
- 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. The default XX: MetaspaceSize value for a 64-bit server-side JVM 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.
* jdk8 and later: * JPS -> jinfo-flag PermSize [process id] * -xx :PermSize=100m -xx :MaxPermSize=100m * * jdk8 and later: JPS -> jinfo-flag MetaspaceSize [process ID] * -xx :MetaspaceSize=100m -xx :MaxMetaspaceSize=100mCopy the code
Methods area OOM
- 1. To resolve 00M or heap space exceptions, a common approach 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.
- 2. If there is a memory leak, you can further check the leak object’s reference chain to GC Roots by using 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 GC Roots 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 (a -xmx and a Xms), compared with the machine physical memory to see if can also big, check whether there is some objects from the code _ life cycle is too long, the state holding time is too long, Try to reduce the memory consumption of the program’s runtime.
The following code will be submitted to the Exception in the thread in JDK8 environment "is the main" Java. Lang. OutOfMemoryError: Compressed class space error
/** * jdk6/7中 : * -xx :PermSize=10m -xx :MaxPermSize=10m ** jdk8中 : * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m * */ public class OOMTest extends ClassLoader { public static void main(String[] args) { int j = 0; try { OOMTesttest = new OOMTest();
for(int i = 0; i < 10000; I++) {// create a ClassWriter object, which is used to generate the binary bytecode ClassWriter ClassWriter = new ClassWriter(0); // Specify the version number, modifier, class name, package name, parent class, interface classWriter.visit(opcodes.v1_6, opcodes.acc_public,"Class" + i, null, "java/lang/Object", null); Byte [] byte[] code = classwriter.tobytearray (); byte[] code = classwriter.tobytearray (); // Class load test.defineclass ("Class"+ i, code, 0, code.length); / / Class object j++; } } finally { System.out.println(j); }}}Copy the code
4. Internal structure of the method area
The 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:
- ① 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 (a subset of public, abstract, final)
- ④ An ordered list of direct interfaces of this type
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).
Methods 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 (a subset of public, private, protected, static, final, synchronized, native, abstract)
- Bytecodes, operand stack, local variable table and size of methods (except abstract and native methods)
- 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 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() {
System.out.println("hello!"); }}Copy the code
Class variables declared as final are handled differently; each global constant is assigned at compile time.
Order. Class bytecode file, right-click in Terminal, Open console, Javap -v -p Order. Class > tst.txt decompile the bytecode file into a TXT file. == static final constant number is assigned at compile time. This is different from the static variable count, which is not modified by final, which is assigned == in preparation for class loading
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
Run-time constant pool
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. In Java, bytecodes require data, and usually that data is too large to be stored directly in bytecodes, or another way, you can store it in a constant pool and the bytecodes contain references 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() {
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
A constant pool, which can be viewed 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 where literal and symbolic references == are generated at compile time and 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 over Class file constant pools is that == is dynamic ==.
- String.intern()
- Another important feature of run-time constant pools over Class file constant pools is that == is 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.
5. Example of using method area
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
The bytecode instruction for the main method
0 sipush 500
3 istore_1
4 bipush 100
6 istore_2
7 iload_1
8 iload_2
9 idiv
10 istore_3
11 bipush 50
13 istore 4
15 getstatic #2 <java/lang/System.out>
18 iload_3
19 iload 4
21 iadd
22 invokevirtual #3 <java/io/PrintStream.println>
25 return
Copy the code
6. 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 earlier: Permanent generation, where static variables are stored
- Jdk1.7: permanent generation exists, but has been “de-permanent”, string constant pool, static variables removed, stored in the heap
- Jdk1.8 and later: No persistent generation, type information, fields, methods, constants are stored in local memory meta-space, but the string constant pool, static variables are still in the heap
What is the permanent substitute to be replaced by meta-space
- 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:
- 1) Setting the space size for the permanent generation is difficult to determine. In some scenarios, if there are too many dynamically loaded classes, O0M in the Perm area is easily generated. 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"
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 ==. - 2) Tuning permanent generations is difficult.
- 1) Setting the space size for the permanent generation is difficult to determine. In some scenarios, if there are too many dynamically loaded classes, O0M in the Perm area is easily generated. 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.
Why should StringTable be adjusted
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.
How do I prove that static variables exist
/** * staticObj, instanceObj,localWhere is Obj stored? */ public class StaticObjTest { static class Test { static ObjectHolder staticObj = new ObjectHolder(); ObjectHolder instanceObj = new ObjectHolder(); voidfoo() {
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
- 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.
7. Method area garbage collection
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
- 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
- 2. The field name and descriptor
- 3. Method name and descriptor
- 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.
- · Determining whether a constant is “obsolete” is relatively easy, while determining whether a type is “no longer in use” 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 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.
8. To summarize
Interview questions:
baidu
Three aspects: 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:
When will objects become obsolete in the JVM 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 have been made to the memory model of the JVM in Java8
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?
JVM learning code and notes
【 code 】 github.com/willShuhuan… JVM_02 Class loading subsystem JVM_03 Run time data area 1- [program counter + vm stack + local method stack] JVM_04 Local method interface JVM_05 Run time data area 2- heap JVM_06 run time data area 3- Method area JVM_07 JVM_08 Execution Engine JVM_09 String constant pool StringTable JVM_10 Garbage Collection 1- Overview + Related algorithm JVM_11 Garbage Collection 2- Concepts related to garbage collection JVM_12 Garbage collection 3- Garbage collector