If you find the content helpful, give it a thumbs up and encourage you to update 😂.

This article continues to be updated, the latest version is: JVM Memory Structure

Come on! New day, new beginning 😘

JVM runtime data area

In one sense, the Memory structure of the Java virtual machine is equal to the run-time data area. There is no such thing as a memory structure in the Java Virtual Machine Specification, which uses the term run-time data area. The memory structure just sounds more appropriate, more graphic.

The JVM (Java Virtual Machine) is a Virtual host used to execute Java programs. The actual job of the JVM is to translate the compiled class code (bytecode) into Machine code that the underlying operating system can run and execute the calls. This is why A Java program can be “written once, run anywhere” (because it generates instructions for specific operating systems). If we compare the core library API to a mathematical formula, then the knowledge of the Java Virtual Machine is like the derivation of the formula. Knowing mathematical formulas is good for exams, but knowing the reasoning behind them is much better for remembering and understanding. And, in those cases where we don’t have a formula, we know how to solve it.

There are many kinds of JVMS, such as the HotSpot virtual machine, which is the default JVM in the Sun/OracleJDK and OpenJDK and is the most widely used JVM today. The JVM is generally referred to as the HotSpot VIRTUAL machine, as in this article.

First, to give a more intuitive and clear impression, I drew a simple memory structure diagram, which shows the heap, thread stack, and other areas I will refer to later, and explains what is thread private and thread shared.

Thread exclusive areas can contain three types of data areas:

  • Program Counter Register
  • VM Stack
  • Native Method Stack

The thread shared area contains the following two types of data areas:

  • Method Area
  • Heap (Heap)

Outside of the JVM, in local memory, there is direct memory and Metadata, which in JDK 1.8 was our previous persistent generation.

The difference is that the string constant pool in the persistent generation in JDK 7 was moved to heap memory in JDK 8, and the rest (Class file constant pool, runtime constant pool) was moved to metadata.

Different areas of the JVM have different memory footprint, with the heap generally being the largest and the program counter small. So what would be the largest area? Is, of course, the most “object” in Java.

Java constant pools: Class file constant pools, runtime constant pools, and of course, global string constant pools, and primitive type wrapper Class object constant pools

Thread private

Program counter (PC)

In the JVM specification, each thread has its own program counter, and only one method is executing per thread at any one time, known as the current method. The program counter stores the JVM instruction address of the Java method being executed by the current thread; Or, if you are executing a local method, an unspecified value (undefined).

The definition of the program counter in the JVM, as a kind of virtual machine, the JVM without instruction register, it is based on the stack + program counter architecture to complete the execution method, it can be seen as the current thread performed by the number of rows in the bytecode indicator, branches, loops, jumps, exception handling, thread to restore basic functions such as all need to rely on the counter

The role of the program counter multithreaded Java virtual machine is through the thread switching in turn and allocate processor execution time, therefore, in order to thread after switching to restore to the execution of the right position, each thread requires a separate program counter, counter each other between every thread, independent storage, We call this type of memory area “thread-private” memory.

Program counters are characterized by a small memory space. Threads are private; each thread has its own program counter. Life cycle: Created as a thread is created and destroyed as a thread terminates. Is the only memory region where OutOfMemoryError does not occur.

Java Virtual Machine Stack (Java Virtual Machine Stack)

Like program counters, the Java Virtual Machine Stack is thread-private and has the same life cycle as a thread. The virtual machine stack describes the thread-memory model of Java method execution; Each thread creates a virtual Stack with Stack frames that correspond to each Java method call. When I talked about program counters earlier, I mentioned the current method; Similarly, at any point in time, there is only one active stack frame, usually called the current frame, and the class of the method is called the current class. If another method is called in this method, a new stack frame is created as the current frame until it returns a result or completes execution. The ONLY two direct operations the JVM does to the Java stack are to push and unload stack frames. The stack frame stores local variable table, operand stack, dynamic link, definition of normal or abnormal exit of method, etc.

The local variable table holds the various basic data types, object references, and returnAddress types known at compile time.

  • Basic types: There are eight basic types
  • Object reference: The reference type, which is not equivalent to the object itself, depending on the virtual machine

Now, it may be a reference pointer to the object’s starting address, a handle to the object, or some other location associated with the object.

  • ReturnAddress: refers to the address of a bytecode instruction.

64-bit long and double data occupy two local variable slots, and the rest occupy only one. The memory space required for the local variable table is allocated at compile time. When entering a method, how much local variable space the method needs to allocate in the frame is completely determined, and the size of the local variable table does not change during the method run.

There are two types of exceptions that occur in the Java virtual machine stack, which are specified in the virtual machine specification:

  • If a thread request allocates more stack capacity than the maximum allowed by the Java virtual machine stack, the Java virtual machine will throwStackOverflowErrorThe exception; Aka stack overflow error! Method recursively calledStackOverflowErrorAbnormal results.
  • If the Java virtual machine stack can be dynamically extended and there is not enough memory to create the corresponding Java virtual machine stack when trying to extend or when creating a new thread, the virtual machine will be thrownOutOfMemoryErrorThe exception. OOM memory overflow error! (Too many threads started)

Of course, the JVM stack can be resized with the -xss parameter!

Native Method Stack

It is very similar to the Java virtual machine stack in that it supports calls to local methods, and each thread creates one. Like the Java virtual machine stack, the local method stack area throws StackOverflowError and OutOfMemoryError exceptions

Threads share

Heap (Heap)

The Java heap is the largest area of memory that is occupied, and the Java heap is used to hold object instances and arrays, which means that objects in our code are stored there with the new keyword new.

For normal objects, the JVM creates the object on the heap first, and then uses references to it elsewhere. For example, store this reference in a local variable table in the virtual machine stack.

For basic data types (byte, short, int, long, float, double, char), there are two cases. As we mentioned above, each thread has a virtual machine stack. When you declare an object of primitive data type in the method body, it is allocated directly on the stack. In other cases, it’s all on the heap.

Note that things like the int[] array are allocated on the heap. Arrays are not basic data types

This became the main camp for the garbage collector, hence the nickname GC heap, and a single JVM process has one and only one Java heap. According to the rules of the garbage collector, we can further divide the Java heap, as shown in the following figure:As can be seen From the figure above, the Java heap is not simply a whole region. In fact, the Java heap is divided into two regions: the new generation and the old generation, and the young generation is further divided into Eden region, From Survivor 0 region, and To Survivor 1 region. The default VM configuration ratio is Eden: from: to = 8:1:1. To put it simply:

Java heap = old generation + New generation New generation = Eden + S0 + S1 Default Eden: from: to = 8:1:1

JVM parameters can be used to dynamically control the size of the Java heap. There are many JVM parameters that can be used to dynamically control the size of the Java heap.

-Xms: indicates the initial size of the heap capacity (the heap includes the new generation and the old generation). For example, -xms 20m-xmx: indicates the total (maximum) size of the heap. For example: -xmx 30M Note: It is recommended to set -xms and -xmx to the same value to avoid the JVM reallocating memory after each garbage collection is complete! -Xmn: Indicates the capacity of the Cenozoic era. For example, -xmn 10M-XX: SurvivorRatio Sets the ratio of Eden, form, and TO. The default ratio is 8:1:1. For example, -xx: SurvivorRatio=8 indicates the ratio 8:1:1

An OutOfMemoryError, also known as an OOM exception, will be thrown when there is not enough space in the Java heap for instance allocation and the heap cannot be extended

Method Area

The Java Virtual Machine specification defines a method area like this:

It stores structural information for each class, such as runtime constant pools, fields, method data, constructors, and bytecode content for common methods, as well as special methods used during class, instance, and interface initialization.

Due to the early Hotspot JVM implementations, many people used to refer to method sections as Permanent Generation. Oracle JDK 8 removed permanent generations and added Metaspace. In the case of HotSpot virtual machine, in JDK1.7, the method area was called the permanent generation, and since JDK1.8, Metaspace is what we call the method area!

The Method Area, like the Java heap described above, is shared by each thread. It is used to store information about classes that have been loaded by the virtual machine, constants, static variables, and code compiled by the just-in-time compiler. Although the Java Virtual Machine specification describes the method area as a logical part of the Heap, it has an alias called non-heap, which is supposed to distinguish it from the Java Heap.

Meta Space

At this point, you should recall the difference between classes and objects. An object is a living entity that can participate in the running of a program. A class is more like a template that defines a set of properties and operations. So you can imagine. Where in the JVM is the A.class we generated earlier placed?

To answer this question, you have to mention the history of Java. Prior to Java 8, information about these classes was stored in memory in a section called Perm. Earlier versions, and even the run-time constant pools associated with String.intern, are also here. This region has a size limit and can easily cause the JVM to run out of memory, which can cause the JVM to crash.

The Perm zone has been completely abolished in Java 8 in favor of Metaspace. The old Perm area was on the heap, now the meta-space is on the non-heap, so that’s the background. For a comparison, you can look at this graph.

And then, the upside of the meta space is also its downside. With non-heap, you can use the operating system’s memory and the JVM will no longer run out of memory in the method area. However, unlimited use is the death of the operating system. Therefore, the -xx :MaxMetaspaceSize parameter is also used to control the size.

Run-time Constant Pool

This is part of the method area. In the decompiled class file structure, you can see information about version numbers, fields, methods, superclasses, interfaces, and the constant pool. Java’s constant pool can store a wide range of constant information, from compile-time literals to symbolic references that need to be determined at run time, so it stores a wider range of information than a symbol table in a typical language.

OOM

The full name Of OOM is Out Of Memory, so which Of our Memory areas will be OOM? The table below shows that OOM overflow is possible in all areas except the program counter. But the most common is in the heap. So what exactly causes OOM? There are several reasons:

  • The memory capacity is too small and needs to be expanded or the heap size needs to be adjusted.
  • Incorrect reference, memory leak. The relationship with GC Roots was not cut off in time. For example, threads in a thread pool forget to clean up the contents of a ThreadLocal in case of reuse.
  • The range of the interface is not verified, and the external parameters are out of the range. Procedure For example, the number of items per page in a database query.
  • Unlimited use of out-of-heap memory. In a more serious case, the operating system may run out of memory.

This is the end of this article, if you like it, give a like + favorites + follow it!