JVM Memory Model and Memory Area Partitioning in Java
Description:
The Java Memory Model (JMM) defines how variables (especially shared variables) are accessed and how threads interact through memory when a Java program runs on various hardware and operating systems. JVM memory area partitioning refers to the division of memory managed by the JVM at runtime into several distinct data areas, each with a specific purpose. Understanding both is crucial for writing correct and efficient multithreaded programs.
Solution Process/Knowledge Points Explanation:
-
JVM Runtime Data Areas (Memory Area Partitioning)
When a Java program runs, the JVM divides the memory it manages into the following main areas, which are specific "physical" or "logical" memory spaces.-
Program Counter Register
- Description: A small memory space that acts as a line number indicator for the bytecode currently being executed by the thread. The bytecode interpreter works by changing the value of this counter to select the next bytecode instruction to execute.
- Characteristics:
- Thread-Private: Each thread has its own independent program counter, which does not interfere with others.
- When a Java method is being executed, it records the address of the currently executing virtual machine bytecode instruction. If a native method (e.g., C++ code) is being executed, this counter value is undefined.
- This is the only area where the Java Virtual Machine Specification does not specify any
OutOfMemoryErrorconditions.
-
Java Virtual Machine Stacks
- Description: Its lifecycle is the same as that of a thread. Each method execution creates a stack frame for storing the local variable table, operand stack, dynamic linking, method return address, and other information. The process from method invocation to completion corresponds to the pushing and popping of a stack frame in the virtual machine stack.
- Local Variable Table: Stores various basic data types known at compile time (boolean, byte, char, short, int, float, long, double), object references (the reference type, which is not the object itself but may be a pointer to the object's starting address, a handle to the object, or another location related to the object), and the returnAddress type (pointing to the address of a bytecode instruction).
- Characteristics:
- Thread-Private.
- This area specifies two error conditions:
- StackOverflowError: If the stack depth requested by a thread exceeds the limit allowed by the virtual machine (e.g., infinite recursion).
- OutOfMemoryError: If the virtual machine stack can be dynamically expanded but fails to allocate sufficient memory during expansion.
-
Native Method Stack
- Description: Very similar in function to the virtual machine stack. The difference is that the virtual machine stack serves the virtual machine's execution of Java methods (i.e., bytecode), while the native method stack serves the native methods (e.g., methods written in C/C++) used by the virtual machine.
- Characteristics: Like the virtual machine stack, it can also throw
StackOverflowErrorandOutOfMemoryError.
-
Java Heap
- Description: This is the largest piece of memory managed by the JVM. The sole purpose of this area is to store object instances. Almost all object instances and arrays are allocated memory here.
- Characteristics:
- Thread-Shared: Therefore, it is the primary area managed by the Java garbage collector, also known as the "GC heap".
- From a memory reclamation perspective, since most modern garbage collectors are based on generational collection theory, the Java heap is often subdivided into: Young Generation and Old Generation/Tenured Generation. The Young Generation can be further divided into Eden space, From Survivor space, and To Survivor space.
- This area can reside in physically non-contiguous memory spaces as long as it is logically contiguous.
- If there is insufficient memory in the heap for instance allocation and the heap cannot be expanded further, the JVM throws an
OutOfMemoryError.
-
Method Area
- Description: Used to store data such as type information, constants, static variables, and the code cache compiled by the just-in-time (JIT) compiler that have been loaded by the virtual machine.
- Characteristics:
- Thread-Shared.
- Many prefer to call the method area the "non-heap" to distinguish it from the Java heap.
- The Java Virtual Machine Specification imposes very loose restrictions on the method area. Like the heap, it does not require contiguous memory and may choose not to implement garbage collection. However, the primary targets for memory reclamation in this area are constant pool cleanup and type unloading.
- If the method area cannot meet new memory allocation requirements, an
OutOfMemoryErrorwill be thrown.
- Special Note: In the HotSpot VM implementation, the method area has an alias called "non-heap", but more specifically, it is implemented as the Permanent Generation (JDK 7 and earlier) and Metaspace (JDK 8 and later). Metaspace uses native memory rather than memory managed by the JVM and is thus limited by native memory size.
-
Runtime Constant Pool
- Description: It is part of the method area. In addition to version, field, method, and interface descriptions, a Class file contains a constant pool table that stores various literals and symbolic references generated at compile time. This content is stored in the runtime constant pool of the method area after the class is loaded.
- Characteristics: It is dynamic; not only content pre-placed in the Class file constant pool can enter it, but new constants can also be added during runtime (e.g., the
intern()method of theStringclass).
-
-
Java Memory Model (JMM) — Abstract Model for Multithreading
JMM is an abstract concept and does not correspond to any physical memory area. Its main purpose is to address thread safety issues caused by various optimizations (such as CPU instruction reordering and inconsistencies between working memory and main memory) in a multithreaded environment.-
Core Concepts: Main Memory and Working Memory
- Main Memory: Can be roughly understood as the portion of object instance data in the Java heap. All variables (referring to shared variables like instance fields and static fields) are stored in main memory.
- Working Memory: Each thread has its own working memory, which holds a copy of the main memory for variables used by that thread. All operations (reading, assigning, etc.) on variables by a thread must occur in working memory and cannot directly read from or write to main memory variables.
- Interaction Relationship: Different threads cannot directly access variables in each other's working memory. Variable value transfers between threads must be done through main memory. This leads to visibility issues: Thread A modifies shared variable X but hasn't written it back to main memory yet, while Thread B reads the old value of X from main memory.
-
Three Major Problems Addressed by JMM
- Atomicity: JMM directly guarantees atomic access and read/write operations for basic data types (except for the non-atomicity agreement for long and double, but commercial virtual machines ensure their atomicity). For broader atomicity guarantees, JMM provides the
monitorenterandmonitorexitinstructions (i.e., thesynchronizedkeyword) to implicitly ensure it. - Visibility: Refers to when one thread modifies the value of a shared variable, other threads can immediately learn about this modification. JMM achieves visibility by synchronizing the new value back to main memory after a variable is modified and refreshing the variable value from main memory before reading it, relying on main memory as the transmission medium. The
volatile,synchronized, andfinalkeywords can all achieve visibility. - Ordering: Observed within a single thread, all operations are ordered ("thread-internal serial semantics"); but observed from another thread, these operations may appear unordered due to possible instruction reordering. The
volatilekeyword guarantees ordering by prohibiting instruction reordering, whilesynchronizedachieves it through the rule that "a variable allows only one thread to lock it at any given moment."
- Atomicity: JMM directly guarantees atomic access and read/write operations for basic data types (except for the non-atomicity agreement for long and double, but commercial virtual machines ensure their atomicity). For broader atomicity guarantees, JMM provides the
-
Summary and Relationship:
- JVM Memory Area Partitioning describes how the JVM divides memory into blocks at runtime and the purpose of each block. This is a "physical" or "logical" level division.
- Java Memory Model (JMM) describes a set of rules and specifications for how Java threads interact through memory and ensure thread safety in a multithreaded environment. It is an "abstract" concurrency model.
Understanding memory area partitioning is fundamental to understanding how the JVM works, while understanding JMM is key to writing correct and efficient concurrent programs. Both describe the relationship between Java programs and memory from different perspectives.