JVM2.1-Runtime data area: method area, heap, runtime constant pool, Java virtual machine stack, program counter, local method stack; stack and stack frame; runtime data area module and thread private shared relationship; new String Created several objects

During the loading process of the first step of the class loading life cycle, there will be two pieces of content in the memory, the method area and the heap, so will there be other areas in the memory?
The JVM is an abstract computer model, so it must obey the von Neumann computer system model.

Please add a picture description
Therefore, there needs to be an input device, an output device, a memory, an arithmetic unit, and a controller, which means that the input needs to have a place to store data, a place to execute data, and a place to output, and the input is the class loader Help you load the file in, the output is to output it into the machine code of the corresponding platform to run, and the data file is loaded in, there must always be a place to store the data, execute and transfer the data, so the JVM is definitely not a memory-only Regardless of the structure, it will inevitably divide the JVM into different areas.

Why use memory?
If the frequent interaction of the CPU is not handed over to the memory, but to the disk, then with the continuous development of the CPU, the CPU will run faster and faster, and the read and write performance of the disk will definitely not keep up with the read and write speed of the CPU. , even the SSD (Solid State Drive) can’t keep up. Compared with the ordinary hard disk, it only reduces the seek time, or speeds up the time to find data, so the memory is set on this basis. It is used to solve the problem that the waiting cost of the CPU is too large due to the long time of a single IO.

The origin of the development of CPU multi-core number
With the rapid development of CPU processing speed, even the use of memory cannot keep up with the read and write speed of CPU, so CPU manufacturers thought of a way at this time, on each CPU. Add a high-speed buffer to speed up reading and writing.

Please add a picture description

Moore's Theorem:
There are two sayings, one is that for a chip, that is, the IC chip will double the number of transistors that can accommodate it every 18 months; the other is the experience of a person named Moore, he said CPU performance doubles every 18 months.

According to Moore's theorem, even if the performance is doubled, the number of CPUs cannot increase without limit. At this time, the main frequency of the single-core CPU will inevitably have a performance bottleneck. Can't stop, if you want to improve performance, can you add more computing cores? At this time, with the growth of time, the era of CPU multi-core has come.

Cache-based storage can well solve the conflict between processors and memory, but it also introduces a new problem, the memory cache consistency problem.

CPU cache consistency problem
If there are multiple computing cores, each computing core will have its own cache, then the problem at this time is: when multiple processor operations involve the same memory area, then it is possible A so-called cache inconsistency problem arises.

In order to solve this problem, we need each so-called CPU processor runtime, including each computing core, to follow some protocols. The role of this protocol is to ensure data consistency.

The runtime data area structure is roughly designed as follows:

Please add a picture description
It can be seen that there are computing cores in the middle of the CPU, and each computing core corresponds to a high-speed buffer. At this time, the protocol in the middle ensures the consistency of the cache, and then goes to the same main memory.

Java multi-threaded cache consistency
uses a multi-threaded mechanism in the programming language Java. Similarly, multiple tasks will be executed at the same time. In fact, it is analogous to the computing core of a CPU, so there must be an area or a kind of The operation can ensure the consistency of our data, so in the JVM memory, the data storage part must have a part of the area that is obtained by all threads at the same time, then we call that area shared by threads, and each thread will have its own separate work . Memory, when our thread is running, our data will definitely be copied from a main memory of the JVM to our thread's own workspace, so this is actually done with reference to the design of CPU cache consistency.

When our threads are operating, our data must have a unique thread workspace, which we call thread private .

From the above content, we can understand that in the design of software, many aspects refer to and refer to computer principles and computer hardware models, which is also the necessary knowledge for every software developer.

Runtime data area: Run-Time Data Areas

Official website introduction address: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5

insert image description here
To translate, 2.5 is the runtime data area

insert image description here

Method area: Method Area

Let’s understand the method area first
insert image description here
. In short, the above specifications say that the method area is a thread sharing model , which is part of the heap and has an alias called “non-heap”. The purpose is to distinguish it from our real Java heap. Although the specification of the method area is like this, the implementation of the method area is actually different. It will be renamed, and the name of each version may be different.

Because the data area of ​​the JVM is just a specification, and the real implementation, the method area is called metaspace in jdk8, and it is called permanent generation in jdk6, and part of the operation to remove the permanent generation is done in jdk7 (this part first To understand, to know first).

Pare space uses the JVM's own memory, while max space uses direct storage (direct memory, that is, the memory of our system).

In the case of insufficient memory in the method area, OOM will be thrown.

Please add a picture description

Heap: Heap

Learn more about the heap The heap
insert image description here
memory is actually the largest piece of memory managed by the Java virtual machine, and it will be created when the JVM starts and shared by all threads.

It can be determined that the heap is a thread-sharing model , because its process is bound to the JVM. Since it is process-related, it must be thread-shared according to the model.

Runtime constant pool: Run-Time Constant Pool

insert image description here
The runtime constant pool is after the virtual machine completes the so-called class loading process, it will load the constant pool in the so-called class file into the middle of the memory, and it will be saved in the method area.

The constant pool we often refer to refers to the runtime constant pool in the method area.

Open a decompiled bytecode file
insert image description here

You can see that under the constant pool in the class file, there are a bunch of constants used to record symbol references and literal information. It occupies a very large proportion of the content of the class file. This kind of constant pool is also generally called a static constant pool. We These constants will be summarized, and an area dedicated to it will be opened in the middle of the memory to store these data.

The static constant pool will also be loaded into the memory, because if the static constant pool is not loaded into our memory, unless the data of the static constant pool has completed a series of parsing outside the JVM, or has been in The external data has been transformed into the data we want, otherwise it must enter the so-called JVM memory, obviously before entering the JVM, it did not do such a thing, and in the JVM method area, it actually stores Class file information and our runtime constant pool, then at this time, the information of our class file actually contains two parts (and the constant pool ② class information), one part is the so-called class information: including magic The beginning, version number information, and subsequent class information, we can describe the class information as a framework, a specification, and the specific content in this specification is the so-called constant pool filled, and the content is stored by the constant pool.

The runtime constant pool refers to the definition in the official document, that is, each class and each interface opens up a special area in our memory to store part of the data in our static constant pool during the JVM running process. And we will throw OOM when the memory required by the runtime constant pool is insufficient. This area can be regarded as a subdivision of the method area.

How does the runtime constant pool dynamically add data?

For example, intern() in Sting can dynamically add values ​​to the string constant pool.

The string constant pool is also called the String constant pool, which is usually included in the middle of the runtime constant pool.
Including the runtime constant pool, there is actually a class called the constant pool of the basic type of Java encapsulation class, such as Integer and Boolean, but it does not include floating point numbers, such as float and double.

Another problem arises here. In Java 1.8, it has made some changes to the implementation of the method area. That is to say, in versions before 1.7, the method area we use is in the virtual machine, which is the memory of the virtual machine. It will not exceed the upper limit of JVM memory, but in jdk1.8, the implementation metaspace of the method area uses direct memory, which means that it can exceed the memory range of the virtual machine. If the metaspace is beyond the memory range of the virtual machine, then at this time, because the implementation metaspace of the method area uses direct memory, how are the constant pools placed? Are all direct memory used?

Please add a picture description

As can be seen from the figure above, both the string constant pool and the basic type wrapper constant pool in the runtime constant pool use heap memory, that is, belong to the JVM memory, and other constant pools in the runtime constant pool can be extended into direct memory.

So what's the point of designing so many types of constant pools?
Java itself is an object-oriented language, so objects will inevitably be generated continuously.

Generally speaking, the content in the constant pool is frequently used data, and generally speaking, its statement cycle is not too short, so if the JVM does not design the constant pool, the JVM needs to be created and destroyed frequently objects, which will affect the performance of the system. So how to design such a thing? It is necessary to consider whether the sharing of objects can be realized, that is, a class cache operation (but it is not a real cache operation).

For example, in the string constant pool, all the same string constants are merged at the compilation stage, occupying only one space, which can greatly reduce the running time.

For example, when comparing strings, "==" is compared with "equals()", and "==" must be faster than "equals()".
"==" is just an operator symbol in Java. "==" will only judge whether two references are equal, and compare their storage addresses in memory, that is, the heap memory address.
equals() is a method in Java. "equals()" is used to compare whether the contents of two objects are equal, and to judge whether the values ​​of the memory spaces pointed to by two variables or instances are the same. Since all classes are inherited from the java.lang.Object class, if the method is not overridden, the method in the Object class is still called, and the equals method in Object returns the judgment of "==". This is an alternative resource sharing logic, and the design of the thread pool is designed with reference to this idea.

String s1 = new String ("aaa"); How many objects are created in the entire life cycle?
Class loading phase: In fact, new String (“aaa”) already needs to create this object during the class loading phase, and the class will only be loaded once. At this time, the string "aaa" will be placed in the global shared character In the string constant pool, this is what the class loading phase does. At this time, an object has actually been created in the constant pool.
Running phase: the constant pool will be searched, and "aaa" will be found, and since it is a new String, when a new object is created, the object will be created in the heap, so it is necessary to copy the "aaa" of the constant pool to the actual heap , and give the reference of this object to s1.

To sum up:
String s1 = new String ("aaa") creates two objects throughout the life cycle, and each call will generate an object.
One is in the constant pool, the constant pool is "aaa",
the other is in the heap memory, the heap memory is new String("aaa"),
and String s1 = new String("aaa"), "=" will A reference to this object is given to s1.

The process is as follows:
Please add a picture description

String s2 = "bbb"; how many objects are created in the whole life cycle?
String s="bbb", this form of assignment is called direct quantity in java, and it is the only way in Java to generate objects without new, and it is placed in the constant pool instead of in the compressed heap like new. String detention occurs inside the JVM for this form of string, that is, after declaring such a string, the JVM will first look for an object with the value "bbb" in the constant pool, and if so, it will Assign it to the current reference. That is, the original reference and the current reference point to the same object. If not, a new "bbb" will be created in the constant pool. Next time, if there is String s3 = "bbb", s3 will be added Point to the object "bbb", that is, the string declared in this form, as long as the values ​​are equal, any multiple references point to the same object.

Glossary: ​​stack and stack frame

Please add a picture description

Java is a process. After the process runs, there will be a lot of threads in it. The threads go back to execute our methods. The core of the whole Java that can run must be that there are many threads in your current process to help you execute these methods
. , if there is a thread now, and then it is used to execute the method (English for execution: invoke), then at this time, there must be a data structure of the execution method in each thread, which represents the data structure of the execution method of the thread, Then this structure chooses the stack .

The methods in Java are divided into several categories, Java methods, native methods, native methods are used by the JVM itself, and native methods need to be called when calling class libraries and calling native methods. For those who execute The Java method is called the Java virtual machine stack, and the native method is called the native method stack. The translation into words means the native method stack.

Then there will be a Java virtual machine stack in the middle of the current thread to represent the current thread, including if various methods are called, it will store our data in the current stack, then at this time , There must be a lot of methods in a thread, so there must be a smallest storage unit, this structure is called a stack frame .

To put it bluntly, it is the invoke that represents a method, that is to say, it represents the execution of a method. As many methods as there are, I will push as many stack frames into the current stack.

Java virtual machine stack: Java Virtual Machine Stacks

insert image description here
The Java virtual machine stack is an area where a thread executes. We save the method calls in a thread. In other words, the running state of our Java thread will be saved by a virtual machine stack, so the virtual machine stack must be a thread Private, it is created along with the creation of the thread, each method executed by the thread corresponds to a stack frame, when a method is called, a stack frame will be pushed to the stack, and after a method call is completed, the stack frame will be Perform a pop from the stack, which is also the characteristic of the stack, first in last out.

The official also explained that unlimited stack frames cannot be pushed into the stack. If unlimited pushes are made to the stack, throws a StackOverflowError will appear, and the stack overflows.

Think about a problem:
in a JVM process, there will be multiple threads executing, then at this time, if the content in the thread wants to have the execution right of the CPU, it must seize the time slice of the CPU. At this time, for example, thread A executes to stack frame 3 Halfway through the execution, at this time the next thread thread B grabs the CPU time slice, then thread A loses the scheduling right of the CPU, then after B finishes executing, A grabs the execution right of the CPU and switches back to thread A, then at this time How to judge where the stack frame is executed?
So a thread definitely needs to maintain a variable in the thread to record the position where our so-called thread executes. This is called the program counter , and it needs to let the contents of our stack be executed step by step in order.

Program Counter: The pc Register

insert image description here

Program counter, also called PC register.
A JVM supports the execution of multiple execution threads at one time, and each JVM thread has its own program counter, that is, the program counter is private to each thread. If the program counter executes a Java method, it records the address of the bytecode instruction of the JVM. If it executes a native method, the counter is empty. The Java level does not record things at the native level.

Native Method Stacks: Native Method Stacks

insert image description here

The native method stack executes the native method. For example, there are many methods in Object, such as hashCode(). Usually, each thread is allocated its own native method stack when each thread is created. That is, the native method stack is also thread-private.

Runtime data area module and thread private shared relationship

The heap and method area are shared by threads, and the program counter, local method stack, and Java virtual machine stack are private to threads.
Please add a picture description
If you want to understand the content of the runtime data area in more detail, it is the stack frame, because a large part of Java is actually used to store things and execute with a specific algorithm. The algorithm is our own defined method. Then the most important thing is the call of each method, and each method call represents a stack frame, so what is in the middle of the stack frame at this time is what we need to care about.

Guess you like

Origin blog.csdn.net/qq_41929714/article/details/131115931