Overview of the JVM runtime data area

Memory is a very important system resource. It is the intermediate warehouse and bridge between hard disk and CPU, carrying the real-time operation of operating system and application program. The JVM memory layout stipulates the strategy of memory application, allocation and management in the running process of Java, which ensures the efficient and stable running of JVM. There are some differences between JVMs in how memory is partitioned and how it is managed. Take a look at the classic JVM memory layout in conjunction with the JVM virtual machine specification.

The Java Virtual Machine defines several types of runtime data areas that are used during a program’s run time, some of which are created when the virtual machine starts and destroyed when the virtual machine exits. Others are thread-specific, where data areas corresponding to the line are created and destroyed as the thread starts and ends.

Overall JVM architecture

JVM system thread

A thread is the executing unit of a program. The JVM allows multiple threads of an application to execute in parallel

In the HotSpot virtual machine, each thread maps directly to the operating system’s native thread. When a Java thread is ready to execute, an operating system native thread is created at the same time. When the execution of the Java thread terminates, the local thread is also reclaimed

The operating system is responsible for scheduling all threads to whichever CPU is available. Once the local thread initializes successfully, it calls the human run() method in the Java thread

If you use JConsole or any of the debugging tools, you’ll see that there are many threads running in the background. These background threads do not include the main thread that calls public static void main(String[] args) and any threads created by the main thread itself.

The main background system threads in the Hotspot virtual machine are the following

  • Virtual machine threads: Threads that operate only when the JVM has reached a safe point. The reason these operations have to happen in different threads is that they all need the JVM to reach a safe point so that the heap doesn’t change. The execution types of such threads include “stop-the-world” garbage collection, thread stack collection, thread suspension, and biased lock undoing
  • Periodic task threads: Threads are representations of time – periodic events (such as interrupts). They are typically used for the scheduled execution of periodic operations
  • GC threads: These provide support for different kinds of garbage collection behavior within the JVM
  • Compiler thread: This thread compiles bytecode to native code at run time
  • Signal dispatcher thread: This thread receives signals and sends them to the JVM, where it processes them internally by calling the appropriate methods

JVM memory structure

  • Each thread can only access its own thread stack.
  • Each thread cannot access (and cannot see) the local variables of other threads.
  • All local variables of the native type are stored in the thread stack and are therefore not visible to other threads.
  • A thread can pass a copy of the value of a native variable to another thread, but it cannot share the native local variable itself.
  • The heap memory contains all objects created in Java code, regardless of which thread created them. It also covers the wrapper types (for example, Byte, Integer, Long, etc.).
  • Whether you create an object and assign its value to a local variable or to a member variable of another object, the created object is stored in heap memory.

  • If it is a local variable of a native data type, its contents are all kept on the thread stack.
  • If it is an object reference, the local variable slot in the stack holds the reference address of the object, while the actual object content is kept in the heap.
  • The member variables of an object are stored on the heap along with the object itself, regardless of whether the type of the member variable is a native data type or an object reference.
  • Class static variables are stored in the heap, as are the class definitions.

  • To summarize: native data types and object reference addresses used in methods are stored on the stack; Objects, object members and class definitions, static variables on the heap.
  • The heap memory is also known as the “shared heap”. All objects in the heap can be accessed by all threads, as long as they can get the reference address of the object.
  • If a thread has access to an object, it also has access to its member variables.
  • If two threads call the same method on an object at the same time, they can both access the object’s member variables, but each thread’s copy of the local variable is independent.

Overall structure of JVM memory

  • Each time a thread is started, the JVM allocates a corresponding thread stack in the stack space, such as 1MB (-xss1M).
  • Thread stacks are also called Java method stacks. If JNI methods are used, a separate Native Stack is assigned.
  • In the process of thread execution, there are usually multiple methods to form A Stack Trace, such as A calls B, and B calls C. Each time a method is executed, a corresponding stack Frame is created.

JVM stack memory mechanism

  • Stack frames are a logical concept, the exact size of which can be determined after a method has been written.
  • For example, return values need a place to store them, each local variable needs an address space, a stack of operands for instructions, and a Class pointer (a method that identifies the Class to which the stack frame corresponds and points to a Class object that is not in the heap).

JVM heap memory structure

  • Heap memory is the memory space shared by all threads, and the JVM divides the Heap memory into Young generation and Old generation (also called Tenured).
  • The young generation is also divided into three memory pools, Eden space and Survivor space. In most GC algorithms, there are two Survivor Spaces (S0, S1). At any moment we can observe, one of S0 and S1 is always empty, but it is usually small and does not waste much space.
  • Non-heap is still Heap in essence, but it is generally not managed by GC and is divided into three pools of memory regions.
  • Metaspace used to be called the Permanent Generation. Java has changed its name to Metaspace
  • CCS Compressed Class Space, storage Class information, and Metaspace has the intersection
  • Code Cache, which holds local machine Code compiled by the JIT compiler.

CPU and memory behavior

  • The CPU executes out of order
  • The volatile keyword
  • Atomic operation
  • The memory barrier

Java object model

Java Memory Model

The JMM Specification corresponds to the $17.4 Memory Model section of the JSR-133 Java Memory Model and Thread Specification

The JMM specification clearly defines how and when different threads can see values stored in shared variables by other threads; And, if necessary, how to synchronize access to shared variables. The advantage of this is to mask the memory access differences between operating systems of various hardware platforms, which makes Java concurrent programs truly cross-platform.

  • All objects (including internal instance member variables), static variables, and arrays must be placed in heap memory.
  • Local variables, method parameters, and exception-handling statements are not allowed to be shared between threads, so they are not affected by the memory model.
  • When multiple threads access a variable at the same time, as long as one thread is performing a write operation, this phenomenon is called “collision”.
  • The operations that can be affected or perceived by other threads are called inter-thread interaction, which can be divided into read, write, synchronous operation, external operation, and so on. Synchronization operations include volatile reads and writes, locking and unlocking monitors, thread start and end operations, thread start and end operations, and so on. External operations are operations performed on a thread that are outside the context, such as stopping other threads, and so on.
  • The JMM specifies the interaction between threads, regardless of internal thread operations on local variables.

JVM startup parameters

  • Starting with – is the standard parameter, and all JVMs implement these parameters and are backward compatible. Example,-server
  • -d Set system properties. Example,-Dfile.encoding=UTF-8
  • Nonstandard parameters starting with -x are generally passed to the JVM. The default JVM implements these parameters, but there is no guarantee that all JVM implementations will meet them and that backward compatibility is not guaranteed. You can usejava -XCommand to view the non-standard parameters supported by the current JVM. Example,-Xmx8g
  • An unstable parameter starting with -XX: is used exclusively to control the behavior of the JVM, depending on the specific JVM implementation, and may be removed at any time in the next release.

    • -XX: + -flags form, where +- switches Boolean values. Example,-XX:+UseG1GC
    • -XX: Key =value, which specifies the value of an option. Example,-XX:MaxPermSize=256m

1. System attribute parameters

- Dfile. Encoding = utf-8 - Duser. Timezone = GMT + 8 - Dmaven. Test. Skip = true - Dio.net ty. EventLoopThreads = 8 / / you can be so System.setProperty("a", "A100"); String a = System.getProperty("a");

2. Operation mode parameters

  • -Server: Set the JVM to use Server mode, which is characterized by slow startup, but high runtime performance and memory management efficiency, suitable for production environments. In 64-bit JDK environments, this mode is enabled by default and the -client parameter is ignored.
  • -client: The default value before JDK1.7 on 32-bit x86 machines was the -client option. Setting up the JVM to use the Client mode is characterized by a fast startup time, but poor runtime performance and memory management efficiency. It is usually used for development and debugging of client applications or PC applications. In addition, knowing that the JVM can either interpret the execution after loading the bytecode, or compile the code to execute it, you can configure the JVM’s processing mode for the bytecode.
  • -xint: Running in interpreted mode, the -xint flag forces the JVM to interpret and execute all the bytecode, which of course slows performance, usually by a factor of 10 or more.
  • -xcomp: The -xcomp parameter is the opposite of -xint. The JVM compiles all the bytecode into native code the first time it is used, resulting in maximum optimization. [Pay attention to preheating]
  • -xMixed: -xMixed is a mixed mode that mixes explain mode and compile mode, depending on the JVM. This is the default and recommended mode for the JVM. We use java-version to see information like Mixed Mode.

3. Heap memory setting parameters

  • -Xmx, which specifies the maximum heap memory. Such as -xmx4g. This only limits the maximum value of the Heap part to 4g. This memory does not include stack memory, nor does it include memory used outside the heap.
  • -xms, which specifies the initial size of the heap memory space. Such as – Xms4g. Moreover, the specified memory size is not the initial value of the actual allocation by the operating system, but is planned by the GC before it is used. You need to keep -xms and -xmx consistent on the dedicated server, otherwise there may be several FULLGCs when the application starts. Heap memory expansion can cause performance jitter when the two configurations are inconsistent.
  • -Xmn is equivalent to -XX: newSize. This option should not be set with the G1 garbage collector, but can be set in some other business scenarios. The official recommendation is -1/2 to 1/4 of XMX.
  • -XX: maxpermSize =size, which was used before JDK1.7. Java8 allows unlimited Meta space by default. This parameter is invalid.
  • -XX: maxMetaSpacesize = Size. Java8 does not limit the Metaspace by default, and generally does not allow this option.
  • – XX: MaxDirectMemorySize = the size, the system can be used outside of the maximum heap memory, this parameter with – Dsun. Nio. MaxDirectMemorySize effect is the same.
  • -XSS, which sets the number of bytes per thread stack, affects the depth of the stack. For example, -xss1m specifying a thread stack of 1MB is equivalent to -xx :ThreadStackSize= 1M
  1. What if nothing is configured?
  2. Is XMX equal to XMS Settings?
  3. What proportion of machine memory should XMX be set to?
  4. Homework: Draw the relationship between XMX, XMS, XMN, Meta, DirectMemory, and XSS memory parameters

4.GC setting parameters

  • -XX:+UseG1GC: Use the G1 garbage collector
  • -XX:+UseConcMarkSweepGC: Use the CMS garbage collector
  • -XX:+UseSerialGC: Use the serial garbage collector
  • -XX:+UseParallelGC: Use the parallel garbage collector
  • -XX:+UnlockExperimentalVMOptions -XX:+UseZGC // Java 11+
  • -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC // Java 12+

What is the default GC for each JVM version?

5. Analyze diagnostic parameters

  • – XX: + – HeapDumpOnOutOfMemoryError option, when an OutOfMemoryError, namely memory (heap memory) or persistent generation, automatic Dump heap memory.

    • Sample usage: Java – XX: + HeapDumpOnOutOfMemoryError Xmx256m ConsumeHeap
  • – XX: HeapDumpPath options, and HeapDumpOnOutOfMemoryError collocation is used, specify the memory Dump files to record. If not specified, it defaults to the working directory from which to start the Java program.

    • Sample usage: Java – XX: XX: + HeapDumpOnOutOfMemoryError – HeapDumpPath = / usr/local/ConsumeHeap
    • Automatically dumped hprof files are stored in /usr/local/
  • -XX: onError option, which is the script to execute in the event of a fatal error.

    • For example, write a script to record the error time, execute a few commands, or curl the URL of an online alarm. Example usage: java-XX: onError =” GDB – %p” myApp
    • You can find a formatted string of %p, representing the process PID.
  • -XX:OnOutOfMemoryError option, the script to execute when an OutOfMemoryError is thrown.
  • -XX: errorFile =filename option, fatal error log filename, absolute path or relative path.
  • -xdebug-xrunjdwp :transport= DT_Socket,server= Y,suspend= N,address=1506, remote debug

6. The JavaAgent parameters

Agent is a black technology in the JVM, which can do many things in a non-intrusive way, such as injecting AOP code, performing statistics, etc., with very large permissions. This is a brief introduction to the configuration options, but the details need to be specific.

The syntax for setting Agent is as follows:

  • -agentlib:libname[=options] -agentlib:libname[=options] Enable native agent, see LD_LIBRARY_PATH path.
  • -agentPath :pathname[=options] Enable native agent.
  • -javaAgent: jarPath [=options] -javaAgent: jarPath [=options] -javaAgent: jarPath [=options] -javaAgent: jarPath [=options] -javaAgent: jarPath [=options]
  • -xNoAgent disables all agents. The following example turns on CPU usage time sampling:

    • JAVA_OPTS=”-agentlib:hprof=cpu=samples,file=cpu.samples.log”