Akik That man

Address: https://juejin.cn/post/1

Disclaimer: This article is the author’s original, has been published with his permission, please do not reprint without the original author’s permission

Writing in the front

By the end of this article you will know:

  • Java’s memory model.

  • Java memory partition.

  • Global variables, local variables, objects, instances, and locations in memory.

  • JVM reordering mechanism.

  • JVM atomicity, visibility, order.

  • Understand the Volatile keyword thoroughly.

Java’s memory model

The Java Memory Model is also known as the Java Memory Model, or JMM. The JMM defines how the Java Virtual Machine (JVM) works in computer memory (RAM). The JVM is the entire computer virtual model, so the JMM belongs to the JVM. You don’t have to understand the threaded JMM to understand Java. The Java memory model defines the visibility of shared variables between multiple threads and how shared variables can be synchronized when needed. Shared memory areas are covered here, and will be covered later in Java memory partitions. In simple terms, JMM explains the problem that when multiple threads access the same variable again, and one thread changes the value of the variable but does not write to main memory, the other thread will read the old value and cannot get the latest value. Ok, let’s see what the memory model is:

The Java memory model defines an abstract relationship between threads and main memory (which can be understood as a shared area in a Java memory partition, described later) : Shared variables between threads are stored in main memory. Each thread has its own private working memory (allocated on the stack), which stores only copies of shared variables used by the thread. Private working memory is an abstract concept that includes areas such as caching, write buffers, registers, and so on. The Java memory model controls communication between threads by determining when a thread’s write to a shared variable in main memory is visible to another thread. Here is the Java Memory model abstraction:

It can be analyzed from the figure that:

1. Each thread has its own working memory when it executes, which contains all variables contained in the method, etc.

2. The private working memory of each thread is not mutually accessible, which explains why we cannot access local variables of one method in another.

3. When a thread wants to access a shared variable, it needs to get it from main memory, and then its own method area is just a copy of the saved variable.

4. When we modify the shared variable, we need to write the changed variable into main memory, so that other threads can get the correct value.

It’s simple:

(1) Thread A flushed the updated shared variables in thread A’s local memory into storage.

(2) Thread B goes to main memory to read the value of the shared variable that thread A has updated before.

That is:

Int I = 1;

In other words, this code is executed by a thread as if the line writes a copy of the value of variable I to its working memory and then writes the value to main memory instead of writing it directly to main memory.

If this proves that using a common variable as a marker to interrupt a thread is not strict, you can move on to my last article on how to interrupt a thread properly.

Java memory partition

In general, Java programs involve the following memory areas when they run:

Register:

JVM internal virtual register, access speed is very fast, the program can not control.

Java virtual machine stack (commonly referred to as “stack”) :

It is thread-private and has the same life cycle as the thread. When each method is executed, a StackFrame is created to store information about local variables, action stacks, dynamic links, method exits, etc. Each method is called until the execution is complete, corresponding to the process of a stack frame in the virtual machine stack from the stack to the stack. It stores basic data types known at compile time (Boolean, byte, char, short, int, float, long, double), object references (reference types), and is not equivalent to the object itself, depending on the virtual machine implementation. It may be a reference pointer to the object’s starting address, a handle to the object or some other location associated with the object, and the returnAddress type (which points to the address of a bytecode instruction).

Pile:

The Java Heap is the largest chunk of memory managed by the Java virtual machine. The Java heap is an area of memory that is shared by all threads and is created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and almost all object instances are allocated memory here. This is described in the Java Virtual Machine specification: all object instances and arrays are allocated on the heap. The Java heap is the primary area managed by the garbage collector.

Methods area:

The Method Area, like the Java heap, is an Area of memory shared by threads that stores information about classes loaded by the virtual machine, constants, static variables, code compiled by the just-in-time compiler, and so on. Although the Java Virtual Machine specification describes the method area as a logical part of the Heap, it has an alias called non-heap, which is supposed to distinguish it from the Java Heap, but it still belongs in the Heap.

Constant pool (actually part of the method area) :

The JVM maintains a constant pool for each loaded type, which is an ordered collection of constants used by that type. This includes direct constants (primitive types, strings) and symbolic references to other types, methods, and fields (1). The data in the pool is accessed by an index just like an array. Constant pools play a central role in Java dynamic linking because they contain all symbolic references to other types, methods, and fields of a type. Constant pools exist in the heap.

Some things to watch out for:

  1. Methods owned by objects and variables involved in them are stored in the stack. Global variables used in methods are stored in the heap along with the object instance, and a copy of the global variable is used in methods.

  2. Member variables of an object, whether primitive or wrapped, are stored in the heap.

  3. The method area, like the heap, is an area shared by threads that holds information about classes loaded by the Java virtual machine, constants, static variables, and even code compiled by the compiler.

  4. When a method on an object is called, it creates its own stack space in the Java stack, and the method is freed as soon as it runs out

  5. Distinguish what is an instance and what is an object. Class a = new Class(); A is called an instance, not an object. The instance is in the stack, the object is in the heap, and manipulating the instance is actually manipulating the object indirectly through the pointer to the instance. Multiple instances can point to the same object.

So let’s take each partition a step further with the code:

Public class Persion{privite String name = "Wang"; Privite static String love = "eat"; Public void init (int age) {if (age < 0) {age = 0; } Log.e(TAG,"Name is "+ name+"Age is "+ age); }}Copy the code

The first thing we know is that when I use Persion p = new Perison(), the Persion p reference is stored in the stack, and the new Perison() object is stored in the heap, including the name member variable; The static variable love is stored in the constant pool. When we call p.it (10), we create the thread’s private stack memory in the thread’s stack, which holds a copy of the age and name shared variables. It should be noted that the heap and method areas are called shared areas, where data can be shared by multiple threads.

JVM reordering mechanism

At the virtual machine level, in order to minimize the impact of empty CPUS when memory is operating much slower than the CPU, the virtual machine executes programs out of order according to its own rules (described below) — that is, code written later may be executed first in chronological order. The code written earlier will be executed — to make the most of the CPU. For example, if the operation is not a=1, but a=new byte[1024*1024], it will run very slowly. If the operation is not a=1, it will run very slowly. Obviously, executing flag=true can advance CPU usage and speed up overall efficiency, as long as there are no errors (more on that later). Although there are two cases: the following code executes before the preceding code; The preceding code starts execution first, but when it is slow, the following code starts execution and finishes before the preceding code. No matter who starts first, the following code has the possibility of ending first in some cases. Let’s look at a simple example:

public void execute(){

int a=0;

int b=1;

int c=a+b;

}Copy the code

Here a=0,b=1 two sentences can be randomly sorted, does not affect the program logic results. Int b = 1; And then int a=0; But we can’t observe it. It’s possible. The sentence c=a+b must be executed after the first two sentences, so there’s no reordering before or after it. Here we have a simple understanding of it.

JVM atomicity, visibility, order

  • atomic

Definition: Reads and assignments to primitive variables are atomic operations, that is, they are uninterruptible and either complete or not performed.

x =3; // statement 1 z = x+y; // statement 3 x++; / / 4Copy the code

Only statements 1 and 2 are atomic operations. Statements 3 and 4 are not atomic operations. Statement 3 contains three operations: 1 reads x first, 2 reads y, and 3 writes z to memory. Statement 4 is interpreted the same way. A statement that contains multiple operations is not atomic; only simple reads and assignments are atomic operations.

  • visibility

This refers to inter-thread visibility, where a thread’s modified state is visible to another thread. That is, one thread changes the result and another thread immediately sees it.

  • order

The Java memory model allows the compiler and processor to reorder instructions, and while reordering does not affect the correctness of single threads, it does affect the correctness of multiple threads.

The Volatile keyword

Here are the three conditions for Volatile:

1. Atomicity is not guaranteed.

2. Keep it organized.

3. Ensure visibility.

When volatile is used to modify a shared variable, the thread accesses the variable by going back to main memory to fetch its value. The cache in its working memory is invalidated, ensuring that each thread accesses the variable from main memory. This is why the Volatile keyword is used to modify shared variables between threads.

conclusion

If you like it, please click “like” before you go. If you are interested, please click “follow” here. I will continue to bring you some new insights, or to describe the painful and difficult principles in plain language

1, Android Studio3.0 update road (in the pit will enter)

2. Android tips: This covers all the ways to “exit an App with one click”

3. I don’t write a line of code to implement the Toolbar! And you’re still wrapping BaseActivity?

At present, more than 5000 people have been interested in joining us, welcome your attention