preface

If there is any problem with wording or understanding, please point it out. The purpose of this article is to mention, not to delve into, but to throw out the points as efficiently as possible

A basic introduction to the JVM

The JVM, short for Java Virtual Machine, is an imaginary computer, a specification. By simulating all kinds of computer functions on the actual computer

The JVM is just like a small computer running on Windows or Linux. It interacts directly with the operating system, not with the hardware, but the operating system can help us complete the work of interacting with the hardware. \

1.1 How are Java files run

Java is just like a text file, except that the text file is written in English and has some indentation.

Our JVM doesn’t know the text file, so it needs a compilation to make it a HelloWorld.class that it reads the binary

① Class loader

If the JVM wants to execute the.class file, we need to load it into a classloader, which acts like a porter, moving all the.class files into the JVM. \

Methods area

The method area is used to store metadata information such as class information, constants, static variables, compiled code, etc

This is where the classloader drops the.class file

(3) the heap

The heap mainly holds stored data, such as object instances, arrays, etc., which belongs to the thread shared area with the method area. That is, they are both thread-unsafe

(4) stack

Stack this is where our code runs. Every method we write is going to run on the stack.

We’ve heard of the term native method stack or native method interface, but we’re not going to talk about either of those two things, because they work in C at the bottom and have nothing to do with Java.

⑤ Program counter

Basically it’s doing a load job, sort of a pointer to the next line of code that we need to execute. Like stacks, they are thread exclusive, meaning that each thread has its own area without concurrency or multithreading problems. \

A small summary

  1. Java files are compiled to become.class bytecode files
  2. Bytecode files are transported to the JVM virtual machine through the class loader
  3. Virtual machine main 5 blocks: method area, heap are thread shared area, there are thread safety issues, stack and local method stack and counter are independent area, there is no thread safety issues, and THE JVM tuning is mainly around the heap, stack two blocks

1.2 Simple code examples

A simple student class \

A main method \

To execute the main method, do the following:

  1. After compiling app.java and getting app. class, the system executes app. class and starts a JVM process that finds a binary file named app. class from the classpath path. Loading App class information into the method area of the runtime data area is called App class loading
  2. The JVM finds the App’s main entry and executes the main method
  3. The first statement in this main is Student Student = new Student(“tellUrDream”), which tells the JVM to create a Student object, but there is no information about the Student class in the method area. So the JVM immediately loads the Student class and puts the Student information into the method area
  4. After loading the Student class, the JVM allocates memory in the heap for a new Student instance, and then calls the constructor to initialize the Student instance, which holds a reference to the type information for the Student class in the method area
  5. Perform student. SayName (); The JVM finds the sayName() bytecode address based on the reference of student, and then locates the method table of the type information of the Student class in the method area based on the reference held by student.
  6. Perform sayName ()

In fact, do not care too much, just need to know that the object instance initialization to look for the class information in the method area, after the completion of the stack to run the method. Find the method in the method table.

Class loader introduction

It is responsible for loading. Class files, they are marked at the beginning of the file, load the bytecode content of the class file into memory, and convert that content into runtime data structures in the method area, and the ClassLoader is only responsible for loading the class file. It is up to the Execution Engine to determine whether it will run

2.1 Class loader process

There are seven steps from the moment a class is loaded into virtual machine memory to the moment it is released: load, validate, prepare, parse, initialize, use, and unload. Verification, preparation, and resolution are collectively referred to as connection

2.1.1 load

  1. Load the class file into memory
  2. Transform static data structures into run-time data structures in the method area
  3. Generate a java.lang.Class object representing this Class in the heap as the entry point for data access

2.1.2 connection

  1. Validation: It is a security check to ensure that the classes being loaded are compliant with JVM specifications and security. It is a security check to ensure that the methods of the class being checked do not cause events that harm the virtual machine at runtime
  2. Static int a = 3; static int a = 3; static int a = 3;
  3. The process by which the virtual machine replaces symbolic references in the constant pool with direct references. Symbolic references, for example, I now import java.util.arrayList, are symbolic references.

2.1.3 initialization

An initialization is simply an assignment that executes a class constructor’s () method. The static int a = 3 example in the preparation phase, which is automatically collected by the compiler for all class variable assignments, is officially assigned to 3

2.1.4 uninstall

The GC removes unwanted objects from memory

2.2 Loading sequence of class loaders

The order in which a Class is loaded is also prioritized, starting at the bottom and going up

  1. The BootStrap this: rt. The jar
  2. Extention ClassLoader: loads the extended JAR package
  3. App ClassLoader: Jar package under the specified classpath
  4. Custom ClassLoader: Custom ClassLoader

2.3 Parent delegation mechanism

When a class receives a load request, it doesn’t try to load it itself, it delegates it to the parent class. For example, if I want to create a new Person, this Person is our custom class, and if we want to load it, we’ll delegate the App ClassLoader. The subclass loader will try to load the request only if the parent Class loaders report that they cannot complete the request (that is, none of the parent Class loaders can find the required Class)

The advantage of this is that no matter which loader loads the classes in the Rt.jar package, the load will eventually be delegated to the BootStrap ClassLoader, which ensures that different classloaders will get the same result.

This is also a way of isolating our code from the JDK code, as I’m going to do right now

public class String(){ public static void main(){sout; }} Copy the codeCopy the code

In this case, our code is bound to report an error, because it actually found the String.class in rt.jar when loading, and then found that there was no main method there either

Three, run time data area

3.1 Local method stack and program counter

For example, if we open the source code of Thread class, we will see that the start0 method has a native keyword modifier, and there is no method body. The native modifier method is the local method, which is implemented in C. Then, these methods are usually placed in an area called the local method stack.

The program counter is essentially a pointer to the next instruction in our program that needs to be executed. It is also the only area of memory where outofMemoryErrors do not occur and the memory footprint is negligible. This memory represents only the line number indicator of the bytecode executed by the current thread, and the bytecode parser selects the next bytecode instruction to execute by changing the value of this counter.

If the native method is executed, the pointer will not work.

3.2 method area

The main function of the method area is to store class metadata information, constants and static variables. When it stores too much information, it will report an error when it cannot meet the memory allocation.

3.3 VM Stack and VM Heap

In a word: stack tube runs, heap tube stores. The virtual stack runs the code and the virtual heap stores the data.

3.3.1 Concept of virtual machine stack

It is an in-memory model for Java method execution. Local variables, dynamic lists, method exits, and stack operations (on and off the stack) are stored exclusively by the thread. Also, if we hear a local variable table, we are talking about the virtual stack

public class Person{ int a = 1; public void doSomething(){ int b = 2; }} Copy the codeCopy the code

3.3.2 Vm Stack Exceptions Exist

If the stack depth requested by the thread is greater than the maximum depth of the virtual machine stack, a StackOverflowError is reported (this error is often seen in recursion). Java virtual machines can also scale dynamically, but as they scale, they are constantly allocating memory, and an OutOfMemoryError is reported when sufficient memory cannot be allocated.

3.3.3 Vm Stack Life Cycle

There is no garbage collection for the stack. As soon as the program finishes running, the stack space will be freed. The life cycle of the stack is consistent with the thread in which it is located.

The eight basic types of variables + object reference variables + instance methods all allocate memory on the stack.

3.3.4 Vm Stack Execution

What we often call stack frame data, which is actually called stack frames in the JVM, is actually methods in Java, which are also stored on the stack.

The data in the stack is in the form of stack frames, which are a set of methods and run-time data. For example, if we execute a method a, it will generate a stack frame A1, which will then be pushed onto the stack. Similarly, method B will have a B1, method C will have a C1, and when this thread completes, the stack will pop C1 first, then B1, then A1. It is a first in, last out, last in, first out principle.

3.3.5 Reuse of local variables

The local variable table is used to store method parameters and local variables defined within a method. Its capacity is the smallest unit of Slot. A Slot can hold up to 32 bits of data.

The VM uses a local variable table in the form of index location. The range is 0, indicating the number of slots in the local variable table. The parameters of the method will be arranged in some order in the local variable table, but we don’t care how they are arranged. In order to save stack frame space, these slots can be reused. When a method is executed beyond a variable, that variable’s slot can be reused by other variables. Of course, if we need to reuse this memory, our garbage collection will not touch it.

3.3.6 Concept of VM heap

JVM memory is divided into heap memory and non-heap memory. Heap memory is also divided into young generation and old generation. Non-heap memory is a permanent generation. The young generation will be divided into Eden and Survivor zones. Survivor is also divided into FromPlace and ToPlace, and the Survivor area of ToPlace is empty. The default ratio for Eden, FromPlace, and ToPlace is 8:1:1. Of course this thing actually can also pass a – XX: + UsePSAdaptiveSurvivorSizePolicy parameters according to the dynamic adjustment of the rate of generated objects

The heap memory holds objects, and garbage collection is collecting these objects and handing them over to the GC algorithm for recycling. Non-heap memory is actually the method area that we’ve already talked about. Permanent generation has been removed in 1.8 and replaced with a MetaSpace. The big difference is that MetaSpace does not exist in the JVM, it uses local memory. And it takes two parameters

MetaspaceSize: initializes the metasspace size and controls GC occurrences. MaxMetaspaceSize: limits the maximum metasspace size to prevent excessive physical memory usage. Copy the codeCopy the code

The reason for the removal can be roughly explained: the change was made by merging HotSpot JVM with JRockit VM, since JRockit does not have permanent generations, but it also indirectly resolves the OOM issue of permanent generations.

3.3.7 Introduction to Eden’s young generation

When we new an object, we will first put the memory allocated by Eden as the storage space. However, we know that the memory for the heap is shared by threads, so two objects may share one memory. What the JVM does here is that each thread allocates a contiguous amount of memory in advance and specifies where objects should be stored, and if it runs out of space, allocates more. So this operation we’re going to call TLAB, if you’re interested.

When Eden space is full, an operation called a Minor GC (that is, a GC that occurs in the young generation) is triggered and the surviving objects are moved to Survivor0. If a Minor GC is triggered when Survivor0 is full, the survivable object is moved to Survivor1 and the FROM and to Pointers are swapped, ensuring that a survivor is always empty and the survivor to which to refers is empty for a period of time. Objects that survive after several Minor GC’s (15), corresponding to the virtual machine parameter -xx :MaxTenuringThreshold. Why 15, because HotSpot records the age in the tag field of the object object and has only 4 bits of space allocated so it can only record up to 15) and moves to the old age. The old age is where long-lived objects are stored, and when it fills up, it triggers the Full GC, the most commonly heard of GC, during which all threads are stopped waiting for the GC to complete. For response-demanding applications, Full GC should be minimized to avoid response timeouts.

In addition, OOM will be generated when the heap memory in the virtual machine is insufficient after full GC. This may be because the heap memory is set too small. This can be adjusted by using -xms and -xmx parameters. It could also be that the objects created in the code are large and numerous, and they keep being referenced so that garbage collection can’t collect them for a long time.

3.3.8 How can I determine if an object needs to be killed

The program counter, virtual machine stack, and local method stack are three areas that live with threads. Memory allocation and reclamation are determined. Memory is naturally reclaimed at the end of the thread, so there is no need to worry about garbage collection. Unlike the Java heap and method area, threads are shared, and memory allocation and reclamation are dynamic. Therefore, the garbage collector focuses on the heap and methods portion of memory.

Determine which objects are alive and which are dead before recycling. The following are two basic calculations

1. Reference counter calculation: add a reference counter to the object. Each time the object is referenced, the counter is incremented by one. There is a situation with this method, however, where the GC can’t reclaim a circular reference to an object.

2. Reachability analysis and calculation: This is a kind of implementation similar to binary tree. A series of GC ROOTS are taken as the starting set of living objects, and the search path goes down from this node into the reference chain, adding the objects that can be referenced by the set to the set. Search When an object does not use any chain of references to GC Roots, the object is not available. Mainstream commercial programming languages such as Java, C#, etc. rely on this method to determine whether an object is alive or not.

Objects that can be used as GC Roots in the Java language are classified as follows:

  1. Objects (local variables) referenced in the virtual machine stack (table of local methods in stack frames)
  2. Objects referenced by static variables in the method area (static variables)
  3. The object referenced by the constant in the method area
  4. JNI is the way the Java virtual machine calls the corresponding C function. New Java objects can also be created through JNI functions. And JNI’s local or global references to objects mark the objects they point to as unrecyclable.)
  5. The Java thread that has been started and not terminated

The advantage of this approach is that it can solve the problem of circular references, but its implementation requires a lot of resources and time, as well as GC (its analysis process reference relationship cannot change, so it needs to stop all processes).

3.3.9 How can I declare an object dead

The first thing that must be mentioned is a method called Finalize ()

Finalize () is a method of Object class, the Finalize () method of an Object will be called automatically by the system only once. When Finalize () is used to escape the dead Object, it will not be called again the second time.

It is not recommended to call Finalize () in our program to save ourselves. It is recommended to forget the existence of this method in Java programs. Because it is not certain when it will be executed, or even if it will be executed at all (an abnormal exit of a Java program), and because it is expensive to run, there is no guarantee that objects will be called in the right order (or even in different threads). It has been deprecated in Java9 and has been gradually replaced with Java.lang.ref. Cleaner (strong, soft, weak, phantom reference), which is lighter and more reliable than Finalize. \

Determining the death of an object requires at least two marks

  1. If the object does not find a reference chain connected to GC Roots after reachability analysis, it will be marked for the first time and filtered. The criterion is to determine whether the object needs to execute the Finalize () method. If objects need to execute finalize(), they are put in the f-queue.
  2. GC marks objects in the F-queue twice. If an object is re-associated with any object on the reference chain in the Finalize () method, it will be moved out of the collection when the second tag is made. If the object has not escaped, it can only be reclaimed.

If the object is dead, how do we recycle it

3.4 Garbage collection algorithm

Will not be very detailed expansion, commonly used mark clearing, copy, mark collation and generation collection algorithm

3.4.1 Mark clearing algorithm

The algorithm can be divided into two stages: “mark” and “clear”. Mark all objects that need to be recycled, and then recycle them. This routine is very simple, there are also shortcomings, the subsequent algorithm is based on this basis to improve.

In fact, it marks dead objects as free memory and records them in a free list. When we need to new an object, the memory management module looks for free memory from the free list to allocate to the new object.

The disadvantage is that the efficiency of marking and clearing is relatively low. And this can cause a lot of fragmentation in memory. This results in not being able to allocate enough contiguous memory if we need to use large chunks of memory. Such as below

The available blocks of memory are scattered, leading to the problem of large memory objects just mentioned

3.4.2 Replication Algorithm

In order to solve the efficiency problem, the replication algorithm appeared. It divides the available memory into two equal parts by capacity, using only one piece at a time. Like survivor, it uses the from and to Pointers. When the fromPlace is full, the surviving objects are copied to another toPlace and the contents of the Pointers are swapped. That solves the fragmentation problem.

The cost of this algorithm is to shrink the memory, so that the heap memory becomes very inefficient

However, the allocation is not 1:1, just like Eden and Survivor are not equal allocation.

3.4.3 Tag sorting algorithm

The copying algorithm has some efficiency problems when the object survival rate is high. The marking process is still the same as the “mark-clean” algorithm, but the next step is not to clean up the recyclable object directly, but to move all the surviving objects to one end and then clean up the memory directly beyond the boundary

3.4.4 Generational collection algorithm

This algorithm does not have any new ideas, but just divides the memory into several blocks according to the different object lifetime. Typically, the Java heap is divided into the new generation and the old generation, so that the most appropriate collection algorithm can be used for each generation. In the new generation, a large number of objects are found dead and only a few survive in garbage collection, so the replication algorithm is selected, and only a small amount of the replication cost of the surviving objects can be collected. In the old days, because the object has a high survival rate and there is no extra space to allocate it, it has to use the “mark-clean” or “mark-tidy” algorithm for recycling.

To put it bluntly, it is the eight immortals crossing the sea.

3.5 (Understand) the various garbage collectors

Garbage collector in HotSpot VM, and applicable scenarios \

As of JDK8, the default garbage collectors are the Parallel Insane and Parallel Old

Starting with JDK9, the G1 collector became the default garbage collector. Currently, the G1 collector has the shortest pause times and no significant disadvantages, making it ideal for Web applications. Test the Web application in JDK8 on a 6GB heap of 4.5G insane. Parallel Recycle the Insane for up to 1.5 seconds. The G1 collector only pauses for 0.2 seconds to recover the same size Cenozoic.

3.6 (Understanding) Common JVM parameters

There are so many JVM parameters, here are just a few of the most important ones, and they are also available through a variety of search engines.

The parameter name meaning The default value instructions
-Xms Initial heap size 1/64 of physical memory (<1GB) By default (the MinHeapFreeRatio parameter can be adjusted), when the free heap is less than 40%, the JVM increases the heap to the maximum limit of -xmx.
-Xmx Maximum heap size 1/4 of physical memory (<1GB) By default (the MaxHeapFreeRatio parameter can be adjusted) when free heap memory is greater than 70%, the JVM reduces the heap to the minimum limit of -xms
-Xmn Young generation size (1.4or lator) Note: The size here is (Eden + 2 survivor space). This is different from the New Gen shown in Jmap-heap. Total heap size = young generation size + old generation size + persistent generation size. When you increase the young generation, you decrease the size of the old generation. This value has a significant impact on system performance. Sun officially recommends setting it to 3/8 of the entire heap
-XX:NewSize Set young generation size (for 1.3/1.4)
-XX:MaxNewSize Maximum young generation (for 1.3/1.4)
-XX:PermSize Set the initial perm gen value 1/64 of physical memory
-XX:MaxPermSize Set the maximum number of persistent generations One fourth of the physical memory
-Xss Stack size per thread After JDK5.0, the stack size of each thread is 1M. Before JDK5.0, the stack size of each thread is 256K. The size of memory required by more applied threads is adjusted. Reducing this value generates more threads for the same physical memory. However, the operating system has a limit on the number of threads in a process, which can not be generated indefinitely. The experience value is about 3000~5000. Generally, small applications, if the stack is not very deep, should be 128K enough. This option has a significant impact on performance and requires rigorous testing. (Principal) It is similar to the interpretation of threadstacksize. The official documentation does not seem to explain this. In the forum there is a sentence like this :-Xss is translated in a VM flag named Threadstacksize
-XX:NewRatio Ratio of young generation (including Eden and two Survivor zones) to old generation (excluding persistent generation) -xx :NewRatio=4 Indicates that the ratio of the young generation to the old generation is 1:4. If the young generation occupies 1/5 of the entire stack, XMS =Xmx and Xmn is set, this parameter does not need to be set.
-XX:SurvivorRatio Size ratio of Eden zone to Survivor zone If set to 8, the ratio of two Survivor zones to one Eden zone is 2:8, and one Survivor zone accounts for 1/10 of the whole young generation
-XX:+DisableExplicitGC Closure System. The gc () This parameter requires rigorous testing
-XX:PretenureSizeThreshold Objects over size are allocated directly in the generation 0 Another case of direct allocation in the older generation is a large array object with no external reference objects in the array.
-XX:ParallelGCThreads Number of threads for the parallel collector This value is best configured to equal the number of processors and also applies to CMS
-XX:MaxGCPauseMillis Maximum time (maximum pause time) for each young generation garbage collection If this time cannot be met, the JVM automatically resizes the young generation to meet this value.

In fact, there are some printing and CMS parameters, I will not list them here

Some aspects of JVM tuning

Based on the JVM we just covered, we can try to tune the JVM, mainly the heap memory

Size of data area shared by all threads = size of new generation + size of old generation + size of persistent generation. The persistent generation is generally of a fixed size of 64M. Therefore, increasing the size of the young generation in the Java heap will reduce the size of the old generation (because the old generation is cleaned using FULLGC, so if the old generation is too small, it will increase the fullGC). This value has a significant impact on system performance, and Sun officially recommends setting it to 3/8 of the Java heap.

4.1 Adjust maximum heap memory and minimum heap memory

-xmx — Xms: Specifies the maximum Java heap (default is 1/4 of physical memory (<1GB)) and the initial Minimum Java heap (default is 1/64 of physical memory (<1GB)).

By default (the MinHeapFreeRatio parameter can be adjusted), the JVM increases the heap to the maximum limit of -xmx when the free heap is less than 40%, and reduces the heap to the minimum limit of -xms when the MinHeapFreeRatio parameter is greater than 70%. To put it simply, you keep throwing data into the heap until it’s less than 40% free, and the JVM dynamically allocates less than -xmx. If it’s more than 70% free, it dynamically shrinks but not less than -xms. It’s that simple

During development, the -xms and -xmx parameters are usually configured with the same value, so that the Java garbage collection mechanism does not need to re-delimit the size of the heap after it has been cleaned up.

We execute the following code

System.out.println("Xmx=" + Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); Println ("free mem=" + Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); system.out.println ("free mem=" + Runtime.getruntime (). Println ("total mem=" + Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); // The total space currently available to copy codeCopy the code

Note: The Java heap size is set here, that is, new generation size + old generation size \

Set a VM options parameter

-xmx20m-xms5m-xx :+PrintGCDetails Copies the codeCopy the code

Start the main method again

Here the GC pops up an Allocation Failure, which occurs in PSYoungGen, the young generation

At this time, the obtained memory is 18M, and the free memory is 4.214195251464844M

Let’s now create a byte array and see, execute the following code

byte[] b = new byte[1 * 1024 * 1024]; System.out.println(" allocate 1 MB space to array "); System.out.println("Xmx=" + Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); Println ("free mem=" + Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); system.out.println ("free mem=" + Runtime.getruntime (). Println ("total mem=" + Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); Copy the codeCopy the code

Free memory shrinks again, but total memory remains the same. Java keeps the total MEM value as close to the minimum heap memory size as possible

byte[] b = new byte[10 * 1024 * 1024]; System.out.println(" allocate 10M space to array "); System.out.println("Xmx=" + Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); Println ("free mem=" + Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); system.out.println ("free mem=" + Runtime.getruntime (). Println ("total mem=" + Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); // The total space currently available to copy codeCopy the code

At this point we create a 10 megabytes of data, and the minimum heap memory is not enough. We will find that the current total memory has become 15M, which is the result of applying for memory once.

Now let’s run this code again

System.gc(); System.out.println("Xmx=" + Runtime.getruntime ().maxMemory() / 1024.0/1024 + "M"); Println ("free mem=" + Runtime.getruntime ().freememory () / 1024.0/1024 + "M"); system.out.println ("free mem=" + Runtime.getruntime (). Println ("total mem=" + Runtime.getruntime ().totalMemory() / 1024.0/1024 + "M"); // The total space currently available to copy codeCopy the code

At this point, we manually performed a FULLGC, and then the total memory space changed back to 5.5m, which was the result of freeing the requested memory.

4.2 Adjust the ratio of Cenozoic to old age

-xx :NewRatio – Ratio of the New generation (Eden +2*Survivor) to the old (not including permanent zones)

For example: -xx :NewRatio=4, indicates the Cenozoic era: old age =1:4, that is, the Cenozoic era accounts for 1/5 of the whole heap. If Xms=Xmx and Xmn is set, this parameter does not need to be set.

4.3 Adjust the ratio of Survivor zone to Eden Zone

-xx :SurvivorRatio – Sets the ratio of two Survivor zones to Eden

For example, 8 indicates two Survivor: Eden =2:8, that is, one Survivor accounts for 1/10 of the young generation

4.4 Setting the size of the Young generation and the old generation

-xx :NewSize — Sets the size of the young generation

-xx :MaxNewSize — Sets the maximum value of the young generation

You can test different situations by setting different parameters. Anyway, the optimal solution is of course the official Eden and Survivor ratio of 8:1:1, and there are some instructions attached to these parameters, if you are interested. Anyway, different values of maximum heap memory and minimum heap memory can lead to multiple GCS, so be careful.

4.5 small summary

Adjusting the size of the new generation and the surviving generation for practical purposes, the official recommendation is that the new generation make up 3/8 of the Java heap and the surviving generation make up 1/10 of the new generation

In OOM, remember to Dump the heap to make sure you can troubleshoot field problems. You can export a. Dump file using VisualVM or the Java VisualVM tool that comes with Java.

- Xmx20m - Xms5m - XX: + HeapDumpOnOutOfMemoryError - XX: HeapDumpPath = do you want to output the log path of duplicate codeCopy the code

We can also script the OOM to send us a message when it appears, by sending an email or restarting the program.

4.6 Setting the Permanent Area

-xx :PermSize -xx :MaxPermSize Copies the codeCopy the code

Initial space (1/64 of physical memory by default) and maximum space (1/4 of physical memory by default). That is, when the JVM starts, the permanent area takes up PermSize at the beginning. If there is not enough space, you can continue to expand, but do not exceed MaxPermSize, otherwise you will get OOM.

If you did not run out of heap space and raised OOM, it may be caused by permanent partition. Heap space actually takes up very little, but a permanent section overflow throws OOM.

4.7 Stack parameter tuning for the JVM

4.7.1 Adjust stack space size for each thread

You can adjust the stack space size for each thread with -xss:

After JDK5.0, the stack size of each thread is 1M. Before JDK5.0, the stack size of each thread is 256K. Reducing this value generates more threads for the same physical memory. However, the operating system has a limit on the number of threads in a process, which cannot be generated indefinitely. The experience value is about 3000~5000

4.7.2 Setting the thread stack Size

-xxthreadStackSize: Sets the thread stack size (0 means use default stack size)Copy the code

All of these parameters can be easily tested by writing your own program, so I won’t provide the demo here because of space issues

4.8 (Can be skipped) Introduction to other JVM parameters

There are a lot of different parameters, so I don’t want to say everything, because people don’t really want to go to the bottom.

4.8.1 Setting the Size of memory pages

-xxthreadStackSize: Set the size of the memory page. Do not set it too large, which will affect the size copy code of PermCopy the code

4.8.2 Set quick optimizations for primitive types

-xx :+UseFastAccessorMethods: Sets the original type of fast optimized copy codeCopy the code

4.8.3 Disabling manual GC

-xx :+DisableExplicitGC: Set to disable System.gc()(this parameter requires strict testing) copy codeCopy the code

4.8.4 Setting the Maximum Garbage Age

-xx :MaxTenuringThreshold Sets the maximum garbage age. If set to 0, the young generation object passes through the Survivor zone and goes directly to the old generation. For the older generation of more applications, can improve efficiency. If this value is set to a large value, the young generation object will be copied multiple times in the Survivor zone, which increases the lifetime of the object in the young generation and increases the probability that it will be recycled in the young generation. This parameter is valid only for serial GC. Copy the codeCopy the code

4.8.5 Speed up compilation

-xx :+AggressiveOpts replicates codeCopy the code

Speed up compilation

4.8.6 Improve the performance of the locking mechanism

-xx :+UseBiasedLocking Indicates the replication codeCopy the code

4.8.7 Disabling garbage Collection

-Xnoclassgc copies codeCopy the code

4.8.8 Setting the heap space lifetime

- XX: SoftRefLRUPolicyMSPerMB set per trillion in free heap space SoftReference survival time, the default value is 1 s. Copy the codeCopy the code

4.8.9 Setting objects to be allocated directly in the old age

- XX: PretenureSizeThreshold set object more than how much directly in the old s allotment, the default value is 0. Copy the codeCopy the code

4.8.10 Setting the ratio of TLAB to Eden

- XX: TLABWasteTargetPercent set TLAB accounted for the percentage of Eden area, the default value is 1%. Copy the codeCopy the code

4.8.11 Setting Priority YGC

-xx :+CollectGen0First Specifies whether to YGC before FullGC. The default value is false. Copy the codeCopy the code

finally

I really pulled this thing for a long time. I referred to various materials, including Geek time’s In-depth Disassembly of virtual Machines and Intensive Interview of Java Core Technology, Baidu and summary of some online courses I have been learning. I hope that was helpful. Thank you.

There are now operating their own knowledge planet, free but does not mean nothing. Students interested in the direction of big data can pay attention to it