JVM Memory Structure
Heap and Non-Heap Memory
The JVM memory consists of the following segments:
- Heap Memory, which is the storage for Java objects
- Non-Heap Memory, which is used by Java to store loaded classes and other meta-data, StringPool
- JVM code itself, JVM internal structures, loaded profiler agent code and data, etc.
Heap
The JVM has a heap that is the runtime data area from which memory for all class instances and arrays are allocated. It is created at the JVM start-up.
The heap size may be configured with the following VM options:
- -Xmx<size> - to set the maximum Java heap size
- -Xms<size> - to set the initial Java heap size
By default, the maximum heap size is 64 Mb.
Heap memory for objects is reclaimed by an automatic memory management system which is known as a garbage collector. The heap may be of a fixed size or may be expanded and shrunk, depending on the garbage collector's strategy.
Non-Heap
Also, the JVM has memory other than the heap, referred to as non-heap memory. It is created at the JVM startup and stores per-class structures such as runtime constant pool, field and method data, and the code for methods and constructors, as well as interned Strings.
Unfortunately, the only information JVM provides on non-heap memory is its overall size. No detailed information on non-heap memory content is available.
The abnormal growth of non-heap memory size may indicate a potential problem, in this case you may check up the following:
- If there are class loading issues such as leaked loaders. In this case, the problem may be solved with the help of Class loaders view.
- If there are strings being massively interned. For detection of such problem, Allocation recording may be used.
Stack
The stack is the memory set aside as scratch space for a thread of execution. When a function is called, a block is reserved on the top of the stack for local variables and some bookkeeping data. When that function returns, the block becomes unused and can be used the next time a function is called. The stack is always reserved in a LIFO order; the most recently reserved block is always the next block to be freed. This makes it really simple to keep track of the stack; freeing a block from the stack is nothing more than adjusting one pointer.
Generational Collection
When a technique called generational collection is used, memory is divided into generations, that is, separate pools holding objects of different ages. For example, the most widely-used configuration has two generations: one for young objects and one for old objects.
Young generation collections occur relatively frequently and are efficient and fast because the young generation space is usually small and likely to contain a lot of objects that are no longer referenced.
Objects that survive some number of young generation collections are eventually promoted, or tenured, to the old generation. See Figure 1. This generation is typically larger than the young generation and its occupancy grows more slowly. As a result, old generation collections are infrequent, but take significantly longer to complete.
HotSpot Generations
Memory in the Java HotSpot virtual machine is organized into three generations: a young generation, an old generation, and a permanent generation.
The young generation consists of an area called Eden plus two smaller survivor spaces, as shown in Figure 2. Most objects are initially allocated in Eden.
Garbage Collection Types
When the young generation fills up, a young generation collection (sometimes referred to as a minor collection) of just that generation is performed. When the old or permanent generation fills up, what is known as a full collection (sometimes referred to as a major collection) is typically done.
Serial Collector
With the serial collector, both young and old collections are done serially (using a single CPU), in a stop-theworld fashion. That is, application execution is halted while collection is taking place
Parallel Collector
These days, many Java applications run on machines with a lot of physical memory and multiple CPUs. The parallel collector, also known as the throughput collector, was developed in order to take advantage of available CPUs rather than leaving most of them idle while only one does garbage collection work.
Concurrent Mark-Sweep (CMS) Collector
For many applications, end-to-end throughput is not as important as fast response time. Young generation collections do not typically cause long pauses. However, old generation collections, though infrequent, can impose long pauses, especially when large heaps are involved. To address this issue, the HotSpot JVM includes a collector called the concurrent mark-sweep (CMS) collector, also known as the low-latency collector