preface

During interviews, it’s common to come up with questions about JVM memory. But in a lot of cases, people don’t really make a distinction between the memory model and the memory region, it’s really two layers.

JVM Memory Model (JMM)

The JMM emerged to solve two classic problems in concurrent programming: how threads communicate and how threads synchronize.

  • Threads here refer to active entities that execute concurrently
  • Communication refers to the mechanism by which threads exchange information

Communication: In imperative programming, threads communicate in one of two ways

  • Shared memory (shared memory model: common state of a program shared between threads that communicate implicitly by writing-reading common state in memory)
  • Messaging (messaging model: There is no common state between threads and threads must communicate explicitly by explicitly sending messages)

Synchronization: Synchronization is the mechanism that programs use to control the relative order in which operations occur between different threads

  • In the shared-memory concurrency model, synchronization is explicit, and the programmer must explicitly specify that a method or piece of code needs to be between threadsThe mutexperform
    • The typical shared memory communication is through shared objects
  • In the concurrent model of message delivery, synchronization is implicit because the message must be sent before the message is received
    • Typical messages in Java are wait() and notify()

To summarize:

Communication mode Communication sympathetic Synchronous sympathetic Programmer perspective
The Shared memory Implicit communication According to synchronize According to specified
The messaging According to the communication Implicit synchronization transparent
  • Concurrency in Java uses a shared memory model, where communication between Java threads is always implicit and completely transparent to the programmer.

The abstract structure of the Java memory model

  • From an abstract point of view, the JMM defines an abstract relationship between threads and main memory:
    • Shared variables between threads are stored in Main Memory. Each thread has a private Local Memory where it can read/write a copy of the shared variable.
    • Local memory is an abstraction of the JMM and does not really exist. It covers caching, write buffers, registers, and other hardware and compiler optimizations.
  • Communication between Java threads is controlled by the Java Memory Model (JMM), which determines when writes by one thread to a shared variable are visible to another thread.
    • The JMM provides Java programmers with memory visibility assurance by controlling the interaction between main memory and local memory for each thread.
  • In Java, all instance fields, static fields, and array elements are stored in heap memory, which is shared between threads within the heap. Local variables, Method definition parameters, and Exception Handler parameters are not shared between threads, have no memory visibility issues, and are not affected by the memory model.

Java memory model specifications:JSR 133: JavaTM Memory Model and Thread Specification Revision

Java memory area (runtime data area)

The Java memory area generally refers to the value runtime data area. During the execution of Java programs, the Java VIRTUAL machine divides the memory it manages into different data areas. JDK 1.8 has tweaks to the runtime data area, so it’s slightly different from previous versions.

Prior to JDK 1.8, it wasn’t a problem if you didn’t know the difference between the runtime data area defined by the JVM specification and the corresponding implementation of HotSpot JVM, and of course, most blogs did the same. But after MetaSpace came along, it was necessary to understand the difference between the two, or it was difficult to understand the distinction between method regions, permanent bands, and meta-spaces.

The runtime data area defined by the JVM specification

Reference: JVM specification documentation for JDK8

The Java Virtual Machine Specification, Java SE 8 Edition (Java Virtual Machine Specification) – Runtime Data area (translation)

Six run-time data areas are defined in the specification, The PC Register, The Java Virtual Machine Stacks, The Heap, The Method Area, The Run-time Constant Native Method Stacks can be made available in a Pool of runtime constants.

  • The text also saysEach run-time constant pool is allocated from the Java Virtual Machine's method area.The runtime constant pool is allocated in the JVM’s method area.

So, this is what we see all the time:

  • It is important to note that these run-time data areas defined in the specification are abstract concepts and do not limit implementation. So the run-time data areas implemented by a specific virtual machine are not necessarily isolated from each other. For example, stack frames may be allocated in the heap (e.g. CLDC HI).

Run-time data areas in a concrete Java Virtual machine (in the case of HotSpot VM)

The HotSpot VM profile

HotSpot VM is a virtual machine that comes with the Sun JDK and OpenJDK and is the most widely used Java VIRTUAL machine.

At The JavaOne conference in 2006, Sun announced that it would finally open source Java, and the following year, various parts of the JDK (including HotSpot VM, of course) were released under the GPL, and the OpenJDK was built on top of that. Thus, HotSpot VM becomes a common virtual machine for two JDK projects, Sun JDK and OpenJDK, whose implementations are very similar.

In 2008 and 2009, Oracle acquired BEA and Sun respectively, giving Oracle two excellent Java virtual machines: JRockit VM and HotSpot VM. Oracle has announced that it will complete the integration of the two virtual machines in the near future. (This is also part of the background for a major overhaul of the HotSpot VM runtime data area in JDK 1.8)

The HotSpot VM structure

HotSpot VM combines the virtual machine stack with the local method stack:

PermGen
Meatspace

  • It is difficult to determine the size of information about classes and methods, so it is difficult to specify the size of permanent generation. If the size is too small, it is easy to overflow the permanent generation, while if the size is too large, it is easy to overflow the old generation
  • The removal of persistent generations is an effort to merge HotSpot JVM with JRockit VM, as JRockit does not have persistent generations and does not need to be configured
  • The removal of permanent generations began as early as JDK1.7. In JDK1.7, some of the data stored in the persistent generation has already been movedJava HeapOr is itNative Heap. For example, Symbols have been transferred tonative heap; The literal interned strings is transferred tojava heap; Class statics are transferred tojava heap.

Some differences between permanent generation and meta space

Defined in the JVM specification: Although the method area is logically part of the heap, simple implementations may choose not to either garbage collect or compact it. The method area is logically part of the heap. (prior to JDK1.7 HotSpot VM’s method area was also physically part of the heap)

  • The permanent generation is allocated in the heap (within the JVM), and the meta-space uses direct memory (outside the JVM)
  • Permanent generation overflow:java.lang.OutOfMemoryError: PermGen space, metaspace overflow:java.lang.OutOfMemoryError: Metaspace
  • The permanent generation GC and the old generation GC are bundled together, and when one of them is full, both regions trigger GC; Classes and their metadata in a meta space have the same life cycle as their corresponding class loaders. When a class loader is no longer alive, the GC reclaims the corresponding space in its entirety (each class loader has a separate storage space) without scanning for time-consuming compression operations.