JVM Memory Management: Part 1

Mrinal Gupta
Nerd For Tech
Published in
5 min readOct 9, 2023

Java manages memory on its own and does not explicitly require the developer’s acquaintance in doing so. Then why should programmers indulge themselves in understanding the memory management in Java? Understanding memory management is crucial because it will help programmers create high-performance systems that do not crash or, if they do, know how to troubleshoot or fix them.

What the heck is memory management?

The memory management in Java is simply the allocation and cleanup of space for objects. Java does it automatically. How? you ask!

Garbage Collectors make sure that any garbage( unused objects, references) free up the memory space. That is why we do not have to write memory management logic in our code.

JVM manages two kinds of memory, heap and non-heap. Both are created at the start of JVM. Heap memory we will discuss in detail but for non-heap memory, not much information is provided by JVM except for its overall size.

Java Runtime Data Areas

JVM defines various data areas to be used during the program’s execution. Some data areas are associated with the start and exit of JVM and some are on a thread basis(created when a thread is created and destroyed when a thread is destroyed).

  1. (JVM) Stack: Stack memory is responsible for holding references to heap objects and for storing value types (primitive types), which hold the value itself rather than a reference to an object from the heap. Stack memory in Java is allocated per Thread.
  2. Heap: The heap part of memory stores the actual object in memory. There exists only one heap memory (heap) for each running JVM process. Therefore, this is a shared part of memory regardless of how many threads are running. The heap memory is periodically garbage collected by the framework.
  3. Program Counter (PC) Register: The PC register holds the address of the current instruction. All CPUs have a PC, typically the PC is incremented after each instruction and holds the address of the next instruction to be executed. The JVM uses the PC to keep track of where it is executing instructions, the PC will in fact be pointing at a memory address in the Method Area.
  4. Method area and Runtime constant pool: JVM has a common method area across all threads. It contains per-class elements like constant pool, fields, method local data, method code, constructor codes, etc. which are used in class and initialization of objects/interfaces. The method area is defined as logically part of the heap in the JVM specification.
  5. Native Stack: Methods written in languages other than Java programming languages such as C, and C++ are called native methods. When a thread calls a Java method, a new frame is created and is being pushed onto the Java stack. When a thread calls a native method, the thread switches from the Java stack to the native method stack. The parameters(if any) are pushed on the native method stack. If a native method calls back a Java method, the thread leaves the native method stack and enters in Java stack again.

Not all JVMs support native methods, however, those that do typically create a per-thread native method stack.

Java’s Runtime Data Areas

Heep Memory: Deep Dive

Java’s heap memory consists of the following areas:

  1. Eden Space
  2. First Survivor Space
  3. Second Survivor Space
  4. Old Generation

The first three areas are grouped under the young generation and the fourth area is called the old generation. The maximum theoretical heap limit for the 32-bit JVM is 4G. Due to various additional constraints such as available swap, kernel address space usage, memory fragmentation, and VM overhead, in practice, the limit can be much lower.

Java Heap Memory

PermGen and Metaspace:

The permanent generation is defined as the pool containing all the reflective data of the virtual machine itself, such as class and method objects. Note it is part of the HotSpot JVM only. For instance, there’s no PermGen space in IBM’s J9 JVM implementation. The permanent generation is special because it holds meta-data describing user classes (classes that are not part of the Java language). The JVM keeps track of loaded class metadata in the PermGen. Additionally, the JVM stores all the static content in this memory section. This includes all the static methods, primitive variables, and references to the static objects. PermGen was often involved in generating the well-known OutOfMemory error.

Furthermore, it contains data about bytecode, names, and JIT information. Before Java 7 (same as Java 1.7), the String Pool was also part of this memory. With Java 1.8, Metaspace has replaced Permgen as its successor.

With the advent of JDK8, we no longer have the PermGen. The metadata information is not gone, just that the space where it was held is no longer contiguous to the Java heap. The metadata has now moved to native memory to an area known as the Metaspace. The JDK 8 HotSpot JVM is now using native memory for the representation of class metadata similar to the Oracle JRockit and IBM JVM’s.

The move to Metaspace was necessary since the PermGen was really hard to tune. Also, it was difficult to size the PermGen since the size depended on a lot of factors such as the total number of classes, the size of the constant pools, the size of methods, etc.

Additionally, each garbage collector in HotSpot needed specialized code for dealing with metadata in the PermGen. Detaching metadata from PermGen not only allows the seamless management of Metaspace but also allows for improvements such as simplification of full garbage collections and future concurrent de-allocation of class metadata.

PermGen and Metaspace

The key difference between PermGen and Metaspace is that while PermGen is contiguous to the Java heap memory, Metaspace is not part of Heap. Rather Metaspace is part of Native Memory (process memory) which is only limited by the Host Operating System. PermGen always has a fixed maximum size but Metaspace by default auto increases its size depending on the underlying OS.

That is enough about JVM and how it handles memory. In the next section, we will unfurl the references, what are strong and weak references, and much more. Watch this article for the next one!

Update: Refer below article for next steps.

Into the JVM Memory Management: Part 2 | by Mrinal Gupta | Oct, 2023 | Medium

Happy Coding!

--

--

Mrinal Gupta
Nerd For Tech

Software Developer on weekdays and A reading enthusiast on weekends. Beethoven’s silence and Chopin’s minute waltz intrigue me.