Fundamentals 13 min read

Java 8 Memory Structure Overview

This article explains the Java 8 memory architecture, detailing the differences between JVM-managed memory and native memory, describing each runtime data area such as the program counter, JVM stack, native method stack, heap, method area, and direct memory, and answering common questions about variable storage, native methods, literals and symbolic references.

Top Architect
Top Architect
Top Architect
Java 8 Memory Structure Overview

Java 8 Memory Structure Diagram

Difference Between JVM Memory and Native Memory

When the JVM runs, it partitions the memory it manages into several regions called JVM memory. Memory that is not directly managed by the JVM but resides in physical memory is called native memory. The two differ as follows:

JVM Memory

Its size is controlled by JVM parameters; exceeding the configured limit results in an OutOfMemoryError.

Native Memory

It is limited only by the physical memory capacity, not by JVM parameters.

If native memory usage exceeds physical memory, an OutOfMemoryError is also thrown.

Java Runtime Data Areas

The JVM divides the memory it manages into several areas, some of which are created and destroyed with threads, others with the Java process. According to the Java Virtual Machine Specification, the runtime data areas include:

Program Counter Register

The program counter indicates the line number of the bytecode currently executed by a thread. Changing its value selects the next instruction, enabling jumps, loops, and thread resumption.

Only one thread can run on a processor core at a time; multithreading is achieved by time‑slicing, which requires a per‑thread program counter.

Therefore, the program counter is thread‑private.

JVM Stack

JVM stack is thread‑private and lives as long as the thread does. Each method invocation creates a stack frame containing:

Local variable table (stores primitive types and object references defined in the method).

Operand stack.

Dynamic linking information.

Return address.

When a method finishes, its frame is popped from the stack.

The JVM stack can throw two kinds of errors:

StackOverflowError if the requested stack depth exceeds the configured limit.

OutOfMemoryError if the JVM cannot allocate a new stack frame.

Native Method Stack

Similar to the JVM stack, it is also thread‑private and can throw OutOfMemoryError or StackOverflowError. The key difference is that the JVM stack executes Java methods, while the native method stack executes native (e.g., C/C++) methods.

Java Heap

The heap is the largest JVM memory area, shared by all threads and managed by the garbage collector. It stores object instances, the string constant pool (moved to the heap since JDK 7), static variables, and the Thread‑Local Allocation Buffer (TLAB) which improves allocation efficiency.

The heap size can be fixed or dynamically expanded via the -Xmx and -Xms parameters; exceeding available memory also results in an OutOfMemoryError.

Method Area (MetaSpace)

All threads share the method area. Prior to Java 8 it was implemented as the Permanent Generation and limited by JVM parameters. Since Java 8 it has been replaced by MetaSpace, which resides in native memory and is not limited by JVM flags (though it can still OOM if physical memory is exhausted). The method area stores class metadata, the runtime constant pool, and, before Java 8, the string constant pool and static variables.

Direct Memory

Direct memory is allocated outside the JVM heap using native functions (e.g., via NIO's DirectByteBuffer). It improves I/O performance by avoiding copying between heap and native memory, but it also triggers OutOfMemoryError when physical memory runs out.

Common Questions

What is a native method?

A native method is declared with the native keyword and implemented in another language such as C, allowing Java code to interact with low‑level system resources. Using native methods reduces portability.

Where are class, member, and local variables stored?

Class variables (static) live in the method area before Java 8 and in the heap after Java 8.

Member variables are part of an object instance and reside in the heap.

Local variables are stored in the stack frame of the JVM stack for the executing method.

Where are constants declared with final stored?

The final modifier does not affect the storage location; they follow the same rules as the variable type they belong to.

Relationship between class constant pool, runtime constant pool, and string constant pool

Both the class constant pool and runtime constant pool reside in the method area. The string constant pool was moved to the heap in JDK 7. The class constant pool holds literals and symbolic references generated at compile time; during class loading these are resolved into the runtime constant pool.

What are literals and symbolic references?

Literals are direct representations of data in source code, e.g.:

int a = 1; // this 1 is a literal
String b = "iloveu"; // "iloveu" is a literal

Symbolic references are placeholders (usually class or method names) used during compilation because the actual memory addresses are unknown; they are resolved to real addresses after class loading.

Note: The original article contains promotional messages and QR‑code invitations for a “top‑level architect” community, which are omitted here for clarity.

JavaJVMmemory managementgarbage collectionJava8Runtime Data Area
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.