According to my friend’s message, from today on, I plan to write a series of articles, and then I will make a brain map to add what I want to write
Basics of JVM
How does a Java program actually work?
A Java program is first compiled by Javac into a.class file. The.class file is identified by the JVM. The JVM loads the.class file into the method area and the execution engine executes the bytecode.
The process is as follows: Java file -> compiler -> bytecode ->JVM-> machine code
The relationship between the JVM, the JRE and JDK
First, take a look at this diagram, the most obvious one is JDK>JRE>JVM, that is, JDK contains JRE, JRE contains JVM, so what is the difference between these three? Let’s start with the smallest
JVM: The JVM specifically understands that an achievement is a platform, a virtual machine, that can translate classes into machine-recognized code. Note, however, that the JVM does not generate its own code. It requires people to write code, and it requires a lot of dependency libraries, which requires the JRE
JRE: In addition to the JVM, the JRE also provides a number of libraries, i.e. Jar packages (for example, reading and manipulating files, connecting to networks, IO, etc.), which are the basic classes provided by the JRE. The JVM standard, along with the implementation of a bunch of class libraries, makes up the Runtime environment for Java, better known as the JRE
Java -jar, Java ac, Java -jar, Java ac, Java -jar, Java -jar, Java -jar, Java -jar Or if something is wrong with your code how do you debug it? All of this is provided by the JDK, so the JDK basically gives us some tools, some commands, to compile code, to debug code, to decompile code, and so on.
Why does Java compile once and run everywhere
You can download the corresponding JDK version from the Oracle website, whether it is Windows, MAC, Linux, Unix, or Oracle. You just need to write Java code, because the JVM downloads different versions of the operating system, so we don’t need to care about the differences between the various operating systems, the JVM only recognizes bytecode, So the JVM is decoupled and not directly related to the language.
Java memory region
As you can see from the figure above, the method area and the heap are the same color, and the virtual stack and the local method stack and the program counter are the same color. Therefore, the method area and the heap are thread shared, while the virtual stack and the local method stack and the program counter are thread privateFrom the figure above, you can see that the Java memory area includes the runtime data area and execution engine and local library interfaces and local method libraries
Runtime data area
Runtime data areas include: method area, virtual machine stack, local method stack, heap, and program counter
Just to be clear: Java1.7 and before was also separate from the heap, but implemented in a similar way, and the diagram is slightly inaccurate
The virtual machine stack
The virtual machine stack is thread private, and its life cycle is the same as the thread. The virtual stack describes the thread memory model for Java method execution: each method execution creates a stack frame to hold local variable tables, operand stacks, dynamic links, method exits, and so on.
If you look at this method, the main method calls method A, method A calls method B, and so on. When we run the code, the thread will have a virtual machine stack for it, and when a method is executed, a stack frame will be generatedFirst is the main method, there will be a stack frame, the main call a method, there will be an a method corresponding to the stack frame, and so on, but after, is the last in, first out, stack data structure is like this, finally is to call c method, c method after the execution, c stack frame will go out first, and then continue to b out stack, and so on
What is a stack frame
A stack frame is a data structure used to support method calls and method execution by a virtual machine. A stack frame stores information such as a method’s local variable table, operand stack, dynamic link, and method return address. Each method from call to completion corresponds to a stack frame from push to exit in the virtual machine.
Local variable scale
The local variable table is a set of variable value stores for method parameters and local variables defined within the method. There are eight basic data types, object reference (reference type) and returnAddress (address that points to a bytecode instruction).
The 64-bit long and double data types take up two local variables, and the rest of the data types only take up one.
The operand stack
The operand stack, also known as the operation stack, is a last in, first out (LIFO) stack. As methods execute and bytecode instructions are executed, variables are copied or written from the local variable table or fields of the object instance to the operand stack, and then the stack elements are removed from the stack to the local variable table or returned to the method caller as the calculation proceeds, known as the stack/push operation.
Here to explain the operand stack, is actually a cache, in a computer, memory is used to store data, the CPU is used to calculate, but in between the CPU and memory, operating system, added a three-level cache is used to solve, memory and CPU speed between the gap is too big, the operand stack is quite so three-level cache, The heap and stack (local variable table) are equivalent to memory, and the execution engine is equivalent to CPU
Here’s a class:
public class Person {
public int work(a){
int x = 1;
int y = 2;
int z = (x+y)*10;
return z;
}
public static void main(String[] args){
Person person = newPerson(); person.work(); }}Copy the code
Here, we can disassemble with the javap -c xxx.class command
javap -c Person.class
Compiled from "Person.java"
public class com.zzz.Person {
public com.zzz.Person();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int work();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 10
9: imul
10: istore_3
11: iload_3
12: ireturn
public static void main(java.lang.String[]);
Code:
0: new #2 // class com/zzz/Person
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method work:()I
12: pop
13: return
}
Copy the code
This is where things look a little bit like classes. Instead of using the javap command, I’m going to install the idea plug-in jClass Bytecode Viewer and go to the class file and click show Bytecode with jClasslib in the viewClick on the code of work in the method and you can see the same information as that in the work aboveInt I =1; int I =1; int I =1; This code corresponds to two lines in the decompile,The human part of this plugin is that you can click on the iconst or something like that and it will take you to the official websiteThe int constant I is pushed into the operand stack.Let’s do istroe_1 and see what that means on the websitePop int I off the operand stack and store it in the local variable table at IAnd what you see here is that the operand stack is really like a level 3 cache on the CPU, where the local variable table is equivalent to memory
The iconst_2 and istore_2 are then pushed into the operand stack as they were before, popped out of the operand stack, and stored in the local variable table
The next step is ilOAD_1 and ILOAD_2We’re pushing int at position I into the operand stack, so we’re pushing int at position 1,2 into the operand stackThen execute iADDIadd means to pop 1,2 off the operand stack, add it up, get 3, and push the resultHere, after the execution engine is done, you need to push the stack, because the execution engine, like the CPU, is not used to store the data, so you need the operand stack to hold the data
Bipush 10 is then executedInt (value=10) is pushed into the operand stackImul is then executedPop up two values from the operand stack, multiply them, and push the result onto the operand stackThen we execute istore_3, which takes 30 off the stack and places it in the local variable table 3And then iloAD_3, which, as I said, pushes the position of the local variable table 3 into the operand stack, which is 30Ireturn is then executedBecause our method needs to return, and this explains why we need iload, this iRETURN needs to return from the top of the operand stack, so we need to push 30 to the top of the operand stack. Pops 30 from the operand stack, pushes it into the operand stack of the calling program framework, discards all other values in the operand stack of the current method
Dynamic connection
In the Java Virtual Machine, each stack frame contains a symbolic reference to the method in the run-time constant pool to which the stack belongs. The purpose of holding this reference is to support dynamic linking during method calls
What dynamic concatenation does: converts symbolic references to direct references (more on this later)Copy the code
We’ll talk about dynamic linking later
Method return address
The return address of the method holds the value of the PC register from which the method was called. At the end of a method, there are two ways: normal execution completes, and abnormal exit occurs with an unhandled exception. After the method exits, returns where the method was called, regardless of which method is used. When a method exits normally, the value of the caller’s PC counter is used as the return address, which is the address of the next instruction to the instruction that called the method. For an exception exit, the return address is determined by the exception table, which is generally not stored in the stack frame.
Local method stack
The function of a local method stack is very similar to that of a virtual machine stack, except that a virtual machine stack is a virtual machine that executes Java methods, while a local method stack is a virtual machine that uses a local method (Native method) service.
Features:
- Native method stack loading native method is used to complete the defects in Java (early Java was not perfect, some need to call C++).
- The VM stack enables the VM to perform Java method services, while the local method stack enables the VM to perform Native method services.
- Is thread private and has the same life cycle as threads. Each thread has one.
The Java virtual Machine specification specifies two types of exceptions for this area of the local method stack, just like the Java virtual machine stack: 1. StackOverFlowError: Stack depth requested by a thread > Allowed depth 2. OutOfMemoryError: StackOverFlowError: Stack depth requested by a thread > Allowed depth 3. The local method cannot obtain enough memory for stack extensionCopy the code
Why is a local method stack necessary
Because in the virtual machine, the virtual machine stack is used to handle some internal operations, but calling native methods is not the same as calling Java methods, so for specification, the native method stack appears
PC program counter
A program counter, also known as a PC register, is a small piece of memory that can be seen as an indicator of the line number of bytecode executed by the current thread. In the virtual machine conceptual model, the bytecode interpreter works by changing the value of this counter to select the next byte code instruction to execute. Basic functions such as branching, loop, jump, exception handling, thread recovery, and so on depend on this counter.
Why have a program counter
In an operating system, a CPU has a finite number of logical processor cores. Why is it possible to run 100 threads at once? The CPU uses an optimization called time slicing
What is CPU time slice rotation
The round-robin (RR) method is mainly used for process scheduling in time-sharing system. To implement round-robin scheduling, the system queues all ready processes on a first-in, first-out basis. The incoming process is added to the end of the ready queue. Whenever a process schedule is executed, the process scheduler always selects the first process in the ready queue to run a slice of time on the CPU. A time slice is a small unit of time, usually on the order of 10-100ms. When a process runs out of its allotted time slice, the system’s timer sends a clock interrupt, and the scheduler stops the process, puts it at the end of the ready queue, assigns the CPU to the first process in the ready queue, and asks it to run another time slice, and so on
Popular point, is that if you touch the fish to work, don’t write code well, playing games and you shop at taobao, taobao phase if you something, the game is to play to eat chicken, boss, you can’t do any shopping taobao and game, to cut the screen to type code in the idea, the boss is gone, you open the game, find a grass lie prone to ensure that no one will see you killed you, Then cut to Taobao chat page with the seller to consult goods, and then the boss came again, you cut the screen to the idea, the boss left, you cut to Taobao or eat chicken, so repeatedly, the boss fixed time passing by, games, writing code, shopping Taobao, time is limited, need to be allocated
So in the JVM, you need a program counter that keeps track of where your code is executing, otherwise you don’t know where you are after the time slice has finished, or after the method calls inside the method have finished
PC counter features
- Unlike PC registers in computer hardware, the two are slightly different. Computers use PC registers to store “directives” or addresses, and relative to the virtual machine, THE PC register it is a piece of memory, the virtual machine’S PC register function is also to store directives, more specifically, to store the address of the instructions to be executed
- When the method being executed by the virtual machine is a local method, the VALUE stored in the JVM’s PC register is undefined.
- Program counters are thread private and have the same lifetime as threads; each thread has one
- This memory region is the only region where no OutOfMemoryError condition is specified in the Java Virtual Machine specification
The heap
For Java applications, the Java heap is the largest chunk of memory managed by the virtual machine. The Java heap is an area of memory shared by all threads and created when the virtual machine starts. The only purpose of this memory area is to hold object instances, and “almost” all object instances in the Java world are allocated memory here. Almost “means from the Angle of implementation, along with the development of the Java language, now we can see some signs of the table name of a value type support in the future, even if only consider now, because of instantaneous compiling technology progress, especially the escape analysis technology of increasingly powerful, allocated on the stack, replacement scalar optimization method has led to some subtle changes are happening, So the allocation of Java object instances on the heap is becoming less absolute.
JVM escape analysis you must know: juejin.cn/post/690562… If you want to know more about distribution on the stack, please see this easy to understand article on mine
The characteristics of the pile
- Is the largest chunk of memory managed by the Java Virtual Machine
- The heap is shared by all threads of the JVM
Thread Local Allocation Buffer (TLAB)Copy the code
- Created during vm startup
- The only purpose is to store object instances, and almost all object instances and arrays are allocated here
- The Java heap is the primary area managed by the garbage collector
- This is why the Java heap is often referred to as the “GC heap “. From the point of view of memory collection, the Java heap can also be subdivided into: the new generation, the old generation; The new generation can be divided into Eden space, From Survivor space, and To Survivor space
- The Java heap is discontinuous in the physical storage of the computer, logically continuous, and resizable (controlled by -xMS and -xmx).
- Objects are not removed from the heap immediately after the method is completed, only during garbage collection.
- An OutOfMemoryError will be thrown if there is no memory in the heap to complete the instance allocation and the heap cannot grow any further.
The classification of the pile
Now garbage collectors use generational theory, and the heap space is classified as follows:
In the Java7 Hotspot virtual machine, the Java heap memory is divided into two parts:
- The young generation
- The old s
In Java7 and before, the permanent generation was implemented in a way similar to the heap, but not in the heap. Consider the permanent generation behind the heap space in the figure below as a separate moduleAfter Java8, the permanent generation does not exist because the method area memory is not allocated on the Java heap but stored in the local memory element space, Metaspace
The young and the old
- Young Gen: The Young Gen mainly stores newly created objects. The memory size of the Young Gen is relatively small and the garbage collection is frequent. Young generation divided into 1 Eden Space and 2 Suvivor Spaces (from and to)
- Tenrued Gen: Tenrued Gen mainly holds objects that the JVM considers to have a long lifetime (they still exist after a few garbage collections by Young Gen), are relatively large in size, and are garbage collected less frequently.
The proportion of the new generation and old generation pile structure
The default value is -xx :NewRatio=2, indicating that the Cenozoic occupies 1, the old occupies 2, and the Cenozoic occupies 1/3 of the whole heap
The Eden space and the other two Survivor Spaces have an 8:1:1 ratio
You can adjust this space ratio with the -xx :SurvivorRatio option. Such as: – XX: SurvivorRatio = 8
Almost all Java objects are created in Eden, but 80% of them have a short lifetime and are destroyed once created
As you can see from the figure: heap size = New Generation + old. The size of the heap can be specified by -xms and -xmx
By default, the ratio of Young to Old is 1:2 (which can be specified by the -xx :NewRatio parameter), that is, Young =1/3 of the heap space. Old =2/3 of the heap space size. Among them, Young is subdivided into Eden and two Survivor zones, which are respectively named from and to to distinguish. By default, Eden:from:to=8:1:1 (The JVM can only use Eden and one Survivor field at a time to service an object, so there is always a Survivor field free at any time. Therefore, the actual available memory space of the new generation city is 9/10 (i.e. 90%) of the new generation space.
Object allocation process
JVM designers need to consider not only how and where memory is allocated, but also whether or not there is intermediate fragmentation after the GC performs the collection, since the memory allocation algorithm is closely related to the memory collection algorithm.
Allocation process:
- The new object is going to be in the Garden of Eden. The area size is limited
- When Eden Park is full, the program needs to create objects again, and the JVM’s garbage collector will heap Eden Park for garbage collection (Minor GC), Eden Park no longer referenced by other objects in the destruction of the objects, and then load new objects into Eden Park
- Then move the remaining objects in Eden Park to Survivor0 zone
- If garbage collection is triggered again, the remnant from the previous collection will be placed in Survivor0, and if not, in Survivor1
- If you go through garbage collection again, you go back to the Survivor0 zone, and then to the Survivor1 zone.
- If the cumulative number reaches the default of 15, it enters the old age
- When the old memory is insufficient, the GC is triggered again: The Major GC clears the old memory
- If there is still no way to save the object after the Major GC, an OOM exception will be reported
The process of allocating objects:
Pile of GC
The heap in Java is also the main area for GC garbage collection. There are two types of GC: Partial GC and Full GC.
Partial collector: a collector that does not collect the entire Java heap. It is divided into:
- Minor GC/Young GC: Garbage collection for the new generation
- Major GC/Old GC: Only the Old GC (CMS GC separately recycles the Old GC)
- Mixed GC: Collect the entire generation of garbage collections as well as the old (G1 GC Mixed collection, region collection)
Full heap Collection: A garbage collector that collects the entire Java heap and method area
Young generation GC trigger conditions:
- If the young generation is full, the Minor GC is triggered. If the Eden generation is full, the GC will not be triggered if the Survivor generation is not full
- Minor RAISES a stop the World (STW), which suspends the threads of other users until they are received by garbage collection
In the old era, the Major GC triggers
- An attempt is made to fire a MinorGC when there is insufficient space in the old age. If there is still insufficient space, a Major GC is fired
- If you Major GC, there is still insufficient memory
- The Major GC is more than 10 times slower than the Minor GC.
FullGC trigger mechanism:
- Call system.gc () and the System will execute Full GC, not immediately. There is not enough space in the old age
- The method area has insufficient space
- The average size of the old age is greater than the available memory of the old age through Minor GC
By printing GC information to see the Cenozoic old age and whether GC
-xx :+PrintGCDetails is configured in idea VM Options to print GC
public class GCTest {
public static void main(String[] args) {
//byte[] allocation1 = new byte[60000*1024];
//byte[] allocation2 = new byte[10000*1024];
//byte[] allocation3 = new byte[10000*1024];
//byte[] allocation4 = new byte[10000*1024];
// byte[] allocation5 = new byte[10000*1024];}}Copy the code
Executing the above code results in:You can see that Eden accounts for 8%, from and to account for 0%, and the old age account for 0%, so why does Eden account for 8% for execution and I’m sure you know that, so I don’t need to tell you more, continue
public class GCTest {
public static void main(String[] args) {
byte[] allocation1 = new byte[60000*1024];
//byte[] allocation2 = new byte[10000*1024];
//byte[] allocation3 = new byte[10000*1024];
//byte[] allocation4 = new byte[10000*1024];
// byte[] allocation5 = new byte[10000*1024];}}Copy the code
If you look here, the Eden zone goes directly from 8% to 99%, so let’s go ahead and change the 6 to 7
public class GCTest {
public static void main(String[] args) {
byte[] allocation1 = new byte[70000*1024];
//byte[] allocation2 = new byte[10000*1024];
//byte[] allocation3 = new byte[10000*1024];
//byte[] allocation4 = new byte[10000*1024];
// byte[] allocation5 = new byte[10000*1024];}}Copy the code
So here we have big objects, so we’re straight into the old age, and the new age is the same as when there was no code running in main, which is 0%
At this point, we change 7 back to 6,6000 *1024 when the Eden zone is about to be full, we uncomment Allocation2 and look at the print
public class GCTest {
public static void main(String[] args) {
byte[] allocation1 = new byte[60000*1024];
byte[] allocation2 = new byte[10000*1024];
//byte[] allocation3 = new byte[10000*1024];
//byte[] allocation4 = new byte[10000*1024];
// byte[] allocation5 = new byte[10000*1024];}}Copy the code
If Eden does not have enough space for allocation2, the virtual machine initiates a Young (Minor) GC. If Eden does not have enough space for allocation2, the virtual machine initiates a Young (Minor) GC. During GC, the virtual machine found that Allocation1 could not store Survior space, so the new generation of objects can only be transferred to the old generation in advance. The old age has enough space to store allocation1, so Full GC does not occur
What kind of object goes straight into the old age
Big objects go straight into the old age
Large objects are objects that require a large amount of contiguous space (e.g. strings, arrays). JVM arguments – XX: PretenureSizeThreshold can set the size of a large object, if the object is more than set size goes straight to the old age, not the young generation, this parameter in Serial and ParNew only effective under two collector.
Such as setting up the JVM parameters: – XX: PretenureSizeThreshold = 1000000 (byte) – XX: + UseSerialGC, to carry out the first program will find large object directly into old age
Why is that?
To avoid inefficient replication operations when allocating memory for large objects
Long-lived objects enter the old age
Since virtual machines manage memory in generational collections, it is important to recognize which objects belong in the new generation and which belong in the old. To do this, the virtual machine gives each object an object Age counter.
If the object survives Eden’s birth and the first Minor GC, and can be accommodated by Survivor, it will be moved to the Survivor space with the object age set to 1. The age of an object increases by one year for each MinorGC it survived in Survivor, and when it reaches a certain age (15 years by default, 6 years for CMS collectors, and slightly different for different garbage collectors), it is promoted to the old age. The age threshold at which an object can be promoted to an old age can be set by the -xx :MaxTenuringThreshold parameter.
Dynamic age judgment of objects
If the total size of a batch of objects in a Survivor region is greater than 50% of a Survivor region’s memory size (-xx :TargetSurvivorRatio can be specified), For example, if there is a group of objects in the Survivor area, and the total number of age objects (age 1+ age 2+ age N) exceeds 50% of the Survivor area, then all the objects (age N +) will be put into the old age. The rule is to hope that those who might be long-term survivors will enter the old age as soon as possible. The dynamic object aging mechanism is usually triggered after minor GC.
Old space allocation guarantee mechanism
Before each minor GC in the young generation, the JVM will calculate the remaining free space in the old generation if the available space is less than the sum of all the objects in the young generation (including garbage objects). If this parameter is set, it will see if the size of the available memory in the old age is greater than the average size of objects that entered the old age after each previous minor GC. If the result of the previous step is less than or the previous parameter is not set, then a Full GC will be triggered, collecting both the old generation and the young generation. If there is still not enough space for the new object, then “OOM” will occur. If the remaining objects that need to be moved to the old age after the minor GC are still larger than the available space in the old age, then full GC will also be triggered. If there is still no room for the remaining objects after the Minor GC, then “OOM” will also occur.
Methods area
The method area, like the heap, is an area of memory shared by threads. It is used to store information about classes that have been loaded by the virtual machine, constants, static variables, and code caches compiled by the real-time compiler.
The meta space, the permanent generation, is the concrete implementation of the method area, which is considered a memory space independent of the Java heap, and is mainly used to store the loaded class information
A method area is a “logical partition” of the JVM. Prior to jdk1.7, many developers used to refer to a method area as a “permanent generation” because in a HotSpot virtual machine, designers used a permanent generation to implement the method area of the JVM specification. After JDK1.8, meta-space was used to implement method areas
When the JVM executes a class, it must first load it. When loading a class (loading, validating, preparing, parsing, initializing), the JVM creates a class file. In addition to describing the version, fields, methods, and interfaces of the class, there is also a pool of constants (final modified variables). Symbolic references include the fully qualified names of classes and methods (such as the String class, whose fully qualified name is Java/lang/String), the names and descriptors of fields, and the names and descriptors of methods
Create declarations for each data region of an object:
Characteristics of method area:
- The method area, like the heap, is an area of memory shared by each thread
- The method area is created when the JVM starts and the physical memory space of its instance can be discontinuous, just like the Java heap
- The size of the method area, like the heap space, can be fixed or dynamic
- The objects in the method area determine how many classes the system can hold. If the system defines too many classes, the virtual machine will also run an exception
- Shutting down the JVM frees up memory in this region
Internal structure of method area:
After loading the Class file into memory, the classloader stores the Class information in the method area.
Contents stored in the method area:
- Type information (domain information, method information)
- Runtime constant pools and constant pools
What is a constant pool
Here we use javap -v xxx.class
javap -v Person.class Classfile /Users/xxx/Desktop/coupon/target/classes/com/zzz/Person.class Last modified 2020-12-17; size 572 bytes MD5 checksum c295a3afb5d289652e0225d17f86483f Compiled from "Person.java" public class com.zzz.Person minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #5.#26 // java/lang/Object."<init>":()V #2 = Class #27 // com/zzz/Person #3 = Methodref #2.#26 // com/zzz/Person."<init>":()V #4 = Methodref #2.#28 // com/zzz/Person.work:()I #5 = Class #29 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 LocalVariableTable #11 = Utf8 this #12 = Utf8 Lcom/zzz/Person; #13 = Utf8 work #14 = Utf8 ()I #15 = Utf8 x #16 = Utf8 I #17 = Utf8 y #18 = Utf8 z #19 = Utf8 main #20 = Utf8 ([Ljava/lang/String;)V #21 = Utf8 args #22 = Utf8 [Ljava/lang/String; #23 = Utf8 person #24 = Utf8 SourceFile #25 = Utf8 Person.java #26 = NameAndType #6:#7 // "<init>":()V #27 = Utf8 com/zzz/Person #28 = NameAndType #13:#14 // work:()I #29 = Utf8 java/lang/Object { public com.zzz.Person(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/zzz/Person; public int work(); descriptor: ()I flags: ACC_PUBLIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 2: iconst_2 3: istore_2 4: iload_1 5: iload_2 6: iadd 7: bipush 10 9: imul 10: istore_3 11: iload_3 12: ireturn LineNumberTable: line 6: 0 line 7: 2 line 8: 4 line 9: 11 LocalVariableTable: Start Length Slot Name Signature 0 13 0 this Lcom/zzz/Person; 2 11 1 x I 4 9 2 y I 11 2 3 z I public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: new #2 // class com/zzz/Person 3: dup 4: invokespecial #3 // Method "<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method work:()I 12: pop 13: return LineNumberTable: line 13: 0 line 14: 8 line 15: 13 LocalVariableTable: Start Length Slot Name Signature 0 14 0 args [Ljava/lang/String; 8 6 1 person Lcom/zzz/Person; } SourceFile: "Person.java"Copy the code
If you look at the print, there’s a section that starts with Constant pool, so this is a Constant pool or static Constant pool
The constant pool can be thought of as a table from which the vm instruction finds the class name, method name, parameter type, literal type, and so on to execute.
Runtime constant pool
The constant pool is the repository for the various literal and symbolic references generated during compilation
Runtime constant pool: the runtime representation of the constant pool. The compiled bytecode file contains type information, domain information, method information, etc. The information in the constant pool of the bytecode file is loaded into memory by ClassLoader and stored in the runtime constant pool of the method area. The runtime constant pool holds direct references to the runtime.
The run-time constant pool converts symbolic reference values from the static constant pool into the run-time constant pool after class loading, and replaces the symbolic reference with a direct reference after class resolution.
The runtime constant pool was moved to the heap memory after the jdk1.7 release, in this case the physical space, while the logical space is still in the method area (the method area is the logical partition).
public class Person {
public int work(a){
int x = 1;
int y = 2;
int z = (x+y)*10;
return z;
}
public static void main(String[] args){
Person person = newPerson(); person.work(); }}Copy the code
Work () is a method, but it can also be a symbol. Work () is a symbol, and the public modifier is also a symbol
Running the main method, Person calls the work() method, which is a symbol in the eyes of the JVM
dimension
The method area is a shared memory area similar to the heap space, so the method area is shared by threads. If two threads are trying to access the same class information in the method area, and the class has not yet been loaded into the JVM, then only one thread is allowed to load it and the other thread must wait
In HotSpot virtual machine, Java 7 version has permanent generation of static variables and runtime constant pool transferred to the heap, the rest is stored in the JVM heap memory, and Java8 version has the permanent generation method area removed, and yuan space instead of the permanent generation before, and the dimension of storage location is the local memory.
Meta space size parameter:
- Jdk1.7 and earlier (initial and maximum): -xx :PermSize; -XX:MaxPermSize;
- After JDK1.8 (initial and maximum): -xx :MetaspaceSize; -XX:MaxMetaspaceSize
- After JDk1.8, the size is limited only by the native total memory (if no parameter is set).
Why does Java8 use meta-spaces instead of permanent generations, and what are the benefits?
The official explanation:
The removal of the permanent generation is an effort to fuse the HotSpot JVM with the JRockit VM, since JRockit does not have a permanent generation and therefore does not need to be configured.
Memory often enough or permanent generation of memory, an exception is thrown. Java lang. OutOfMemoryError: PermGen. This is because in JDK1.7, the size of the specified PermGen area is 8M. The class metadata information in PermGen may be collected every time during FullGC, so the recovery rate is low, so the performance is not satisfactory. It is also difficult to determine how much space to allocate for PermGen. The size of PermSize depends on a number of factors, such as the total number of classes loaded by the JVM, the size of the constant pool, and the size of the methods.