This article is participating in the Java Theme Month – Java Debug Notes EventActive link 。

Java Runtime Data Area Java Runtime Data Area A class file is loaded by the ClassLoader into the runtime data area.

So what information does the runtime data area contain?


Java Runtime Data Area distribution

The overall distribution

Program Counter Register

The Program Counter Register is unique to each thread. PC register or PC for short. Used to record which instruction is executed by the current thread. When a thread is scheduled for execution by the CPU, execution continues from the instruction number recorded by the current thread’s PC. Branches, loops, jumps, exceptions, and so on all depend on counters.

JVM Stack

The JVM Stack is unique to each thread. The JVM Stack holds “Stack frames”, and each time a Java method is called, a “Stack frame” is generated and pushed into the JVM Stack, and the corresponding “Stack frame” pops onto the Stack when the method ends.

Because “stack frames” take up memory for specific data structures, “stack overflow” can occur when method calls are too hierarchical (for example, recursive calls with no proper exit set).

Since a “stack frame” represents a method call, what does the specific data structure load? A complete stack frame contains the following sections:

  1. Local variable scale: Used to record local variables generated during method execution. Local variable numbers start at 0, and for an instance method, the 0th local variable is this (note that there is no local variable corresponding to super), followed by the method’s input, and finally the local variable that will occur when the method starts executing.

  2. Operation stack: Mainly stores the parameters and return values needed to execute instructions.

  3. Dynamic linking: When the Method needs to reference some data outside the local variable table (for example, classes in Method Area), there needs to be a link to the data. Dynamic linking is simply providing links to this content.

  4. Return address: when a method called the other way, to suspend the execution of the current “stack frame”, create a new “stack frame” and perform, waiting for a new “stack frame” completes, will result in the current “stack frame”, the return value of address (usually) for the operation of the stack stack, the current “stack frame” to continue.

Native Method Stack

The Native Method Stack is unique to each thread. Similar to the JVM Stack, the Native Method Stack is a Stack structure of services and Native methods (C/C++), commonly used in JNI.

Heap

Heap is shared by all threads. It mainly holds objects created by the new operation. Since the current mainstream garbage collectors use generational collection algorithms, heap memory is often logically partitioned as well.

Heap is divided into Young area (Young generation) and Old area (Old age) in a ratio of 1:2.

Among them, Young zone (Young generation) is divided into one Eden zone and two Survivor zones (abbreviated as S0 and S1 respectively), with a ratio of 8:1:1.

A further introduction to Heap logical partitioning and garbage collection can be found in Java GC

Method Area

Method Area is a Runtime Data Area shared by all threads. Method Area is a logical concept that is regulated by the JVM.

Method areas do not correspond to specific data structures like stacks or heaps. The Method Area is implemented differently in different JDK versions:

  • Prior to JDK 1.8: The Method Area implementation was PermGen. It mainly stores class information, constant pools, static variables, and compiled code. The persistent generation is not collected by the GC, and since class information is stored in the persistent generation, it is easy to run out of the persistent generation memory (new classes are created dynamically during runtime, and the contents of the persistent generation are gradually filled up). The permanent generation must be sized, which is affected by the -xx :PermSize and -xx :MaxPermSize parameters, which in turn are limited by the JVM’s overall heap memory size (in JDK 1.7, the permanent generation is in the heap space). Therefore, the Method Area implemented by the permanent generation is more likely to overflow memory.

  • After JDK 1.8: The implementation of Method Area is Metaspace. The main contents are the same as the permanent generation, but the main contents, such as class meta-information, are no longer in the heap, but the static variables and run-time constant pools in the method area are still in the heap as in JDK 1.7. The metadata area can be specified without size or by using the -xx :MetaspaceSize and -xx :MaxMetaspaceSize arguments. If the size is not specified, the default maximum limit is the physical memory size (the metadata area is not in the heap space, but in local memory). Since the size of the metadata Area is mainly determined by the size of the physical memory, and the metadata Area can be reclaimed by GC, the Method Area implemented by the metadata Area (compared to the Method Area implemented by the permanent generation) has a lower risk of memory overflow.

The following figure clearly shows the difference between JDK 1.7&1.8 heap partition:

When the same unloaded class is accessed by multiple threads at the same time, only one thread is allowed to load it and the other thread must wait.

In JDK 1.7, because the permanent generation is in the heap, the pool of meta-information, static variables, or constants of the class is placed in the heap, and the size is limited by the heap memory, which carries a high OOM risk.

JDK 1.8 does away with persistent generation, and content such as class meta-information is placed in a meta-space, which is limited in size by the physical content. Static variables and constant pools are kept in the heap.