preface

This column is about the basics of the JVM generational model. It will be built from scratch, gradually, and, like the last one, very basic

Actually, this article is all about object allocation: There’s a lot to digesting into the JVM’s vm-to-JVM object allocation strategy, and this article will cover some of the basics.

Summary:

  1. Describes the basic generation model of the JVM and the handling of version upgrades.
  2. Basic concepts and knowledge of object allocation.
  3. How do long-lived objects escape garbage collection into the old age
  4. Description of the core parameters and basic configuration of JVM memory

The JVM’s generational model

The basic generation model of the JVM: young generation, old generation, and permanent generation. Note here the memory model is usually and garbage payback period complementary to each other, modern garbage collector is very complex, and even don’t have the concept of generational, we speak of the new generation of old s are some of the initial design concept, a lot of people learn to more advanced garbage collector may be blind, such as heap memory how to become a piece of, Not previously said that heap memory only the new generation and the old age of this two complete large space?

  • Young generation: most of the objects are born and die. Also, the JVM always allocates objects to the new generation first, and the garbage collection triggered by the new generation is often referred to as Minor GC.

  • Old age: a storage area belonging to a long – lived object, arising from the promotion of the Cenozoic. The old generation typically occupies the largest chunk of memory space in the heap. Garbage collection triggered in the old days is often referred to as Full GC.

  • Permanent generation: note that the permanent generation is not the same as the method area, which mainly stores static constants or class information. The method area can be garbage collected, but the condition is very strict, and the most commonly used constant pool has been moved to the heap after JDK8, the permanent generation and renamed as meta space.

    Why bring in the permanent generation? Permanent generation of design is actually a failure of design, permanent JDK8 waste generation at the same time to replace with the use of local memory element space, greatly reducing the generation of overflow may permanently, because already without the use of virtual machine memory, but the direct use of the native memory storage, there is another benefit is the permanent generation also won’t to rob the heap memory.

Basic understanding of object allocation

The following basic to understand the basic concept of object allocation, these concepts may be in the learning of JAVA has been exposed to, so it is also a simple mention:

  1. Most normal objects are allocated preferentially in the new generation. After the garbage collection thread is started, the long-lived object is promoted to the old age store

  2. Even for objects whose static variables exist in the method area, instance objects are allocated in the heap. However, initialization is triggered only when it is used by a stack frame local variable.

  3. Those allocated on the heap are still preferentially allocated in the new generation, and will be promoted to the old generation after long-term survival.

  4. When the memory space of the new generation is full, the minor GC is triggered. When the old space is Full, the Full GC is triggered, and the Full GC is triggered

Here is a diagram to illustrate the basic concept of object allocation:

The following code is a simple example of how to allocate objects.

public class OneWeek {

    private static final Properties properties = new Properties();

    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = OneWeek.class.getClassLoader().getResourceAsStream("app.properties");
        properties.load(resourceAsStream);
        System.out.println("load properties user.name = " + properties.getProperty("user.name"));
    }/* Run result: load properties user.name=123 #app.properties: user.name=123 */
}
Copy the code

First, when the thread is started, the oneweek.class object is loaded and initialized, the Main() method is pushed into the virtual machine stack, and the stack frame and local variable table are created.

Then, the bytecode engine executes the instructions in the bytecode. As you can see from the code, the method first takes the class file of the current class and calls the current class loader to load the app.properties file into memory. Note that during loading, the char[] array is created to store the loaded contents. As well as creating file IO streams and reading files, this part of the object is allocated to the new generation first.

When the program counter runs to: property.load (resourceAsStream); When this line of code corresponds to the bytecode instruction, it is found that property. class is not loaded, and it is also found that it is a static object, so the current object reference is allocated to the method area for storage. Note that the method area stores the object reference, not the object instance, and the instance is still allocated to the new generation first. But why does it go straight to the old age? Since we know that this static constant can be counted as a long-lived object if it is referenced by other classes, the long-lived object is bound to enter the old age sooner or later, so the graph is directly divided into the old age.

At the same time, we can find that if the new generation of objects exist after garbage collection, they will be automatically promoted to the old generation after garbage collection for storage.

It’s important to note that the objects that come out of new are always strong references. Even if the stack frame local variable is used only once, the reference to the object is not collected immediately with the stack frame, but is collected after the garbage collection thread is opened.

Long-lived objects avoid garbage collection

  1. If the age of the object reaches 15, it will automatically enter the old age.
  2. If big objects cannot accommodate the new generation, they will also directly enter the old age.
  3. Old age also triggers garbage collection, which clears garbage objects that no one references
  4. When certain garbage collector promotion mechanisms are met or certain conditions are met, the new generation of objects may advance into the old generation.

Here’s how they came to be:

What is the age of the object? The age of an object is when the JVM is running. Every time an object in the new generation escapes a garbage collection, the internal reference counter adds 1 to the current age of the object. When the age of the object is added up to 15, the object is promoted to the old age after the next garbage collection. Of course, when the old age is full, if the current object is no longer referenced by GC ROOT, it will still be garbage collected.

Large objects is the most typical case is a string or an array of bytes, because of the need to occupy contiguous memory space, if a new generation can’t accommodate, so there is no doubt that is the need to direct deposit as out in the old old s s, as for the specific parameters of a subsequent article will explain, understand the basic concepts here.

When will garbage collection be triggered? Conditions is undoubtedly the old s not put objects, so why is Full of old s, said the old s objects on a us are from new generation, so there is no doubt is a new generation to fit inside the old s found that the old s, so the old s at this time will be garbage collected, recycling old s is called a Full GC.

After reading the above, we need to consider the timing of the new generation into the old age. Why should we consider this thing? Let’s analyze:

The first is the big object. The big object enters the new generation and finds that the new generation can not be put down. If the old age also finds that it can not be put down, it will be directly Full GC? This is too pessimistic, if the garbage recycling after put down, it is not a waste of performance, not appropriate. Second, new generation must wait until their full into old age, it may be too optimistic, because one thousand new generation there are always some live objects in “waiting” area (survior area) and will not enter old age, middle’t, so this area but lost his value, so is not suitable, not into old age ahead of time.

Core parameters for JVM memory:

The core parameters of the generation are as follows. It is important to note that the parameters are case sensitive, as incorrect input will result in invalid parameters:

  • -Xms: specifies the size of the Java heap memory

  • -Xmx: indicates the maximum size of the Java heap memory

  • -xmn: The size of the new generation in the Java heap. After deducting the new generation, the memory size of the old generation is left

  • -xx :PermSize: permanent generation size ** (JDK8 deprecated, replaced with: -xx :MetaspaceSize) **

  • -xx :MaxPermSize: maximum permanent generation size ** (JDK8 is deprecated and replaced with: -xx :MaxMetaspceSize) **

  • -Xss: specifies the memory size per thread stack

-xms and -xmx are used to limit the total size of the Java heap and the maximum size of the expansion, but are usually set to the same parameter because expansion requires stop world to greatly affect system performance.

-xmn: is the space size of the Cenozoic generation. The old generation is automatically calculated from the total heap size -Cenozoic size.

– xx: permsize and – xx: maxpermsize. The permanent generation size and maximum size are limited, usually 256M is sufficient

– The Xss parameter limits the stack memory size of each thread. This is the size of the virtual machine stack for each thread. It should not be too large, and it should not be too small.

  • After noticing jdk1.8, these two parameters are replaced with-XX:MetaspaceSizeAs well as-XX:MaxMetaspceSize.

Settings for startup parameters?

The startup parameters in IDEA are set as follows:

-Xms1024m
-Xmx2048m
-XX:ReservedCodeCacheSize=500m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-XX:CICompilerCount=2
-Dsun.io.useCanonPrefixCache=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Djdk.attach.allowAttachSelf=true
-Dkotlinx.coroutines.debug=off
-Djdk.module.illegalAccess.silent=true

Copy the code

How to set parameters when Tomcat and Spring Boot are started

  1. Tomcat Configure parameters under Catalina in bin.

  2. In Spring Boot, you can add vm parameters to vm. Options

Will objects in the method area be reclaimed or not?

  • First, all instance objects of the class have been reclaimed

  • The classLoader that loaded the class has been reclaimed

  • There is no reference to the class object.

    If these conditions are met, the method area can be reclaimed. You can find that the reclamation conditions of the method area are very strict.

Conclusion:

This article describes the generation model of the JVM, the new generation, the old age, and then we have some basic concepts for allocating JVM objects in generations, such as object priority allocation in the old age, object age promotion to the old age, and long-lived objects entering the old age after garbage collection. Similarly, The JVM also has some special judgment mechanisms that allow the new generation to get ahead of the old, and these are important optimizations that will be covered in more detail in a future series of articles.

Write in the last

It is important to understand the concept of generational and be familiar with the MEMORY model of the JVM, because modern garbage collectors are evolving and complex and even abandoning the idea of generational. It is necessary to understand the history and process of generational, and non-generational is certainly the future.