Let us much started memory model: as a general people need to know about, the JVM memory area can be divided into: thread stack, heap, static methods area (in fact there are more areas, and here is the JVM memory area, actually Java program can also call native method using direct memory).

This article will focus on these three areas.

  1. Thread stack

Introduction to the

Note that this stack is similar to a stack in a data structure, but not in user mode. To be precise, each Stack Frame it pushes is a program instruction and local variable table, and each method call corresponds to a Stack Frame. The table of local variables includes various basic data types: Boolean, byte, CHAR, short, int, float, long, double, and references to objects. Note that each thread has a separate stack and is isolated from each other.

The size of the stack

The size of the stack can be affected by several factors. One is the JVM parameter -xSS, which is the default value depending on the vm version and operating system.

In Java SE 6, the default on Sparc is 512k in the 32-bit VM, and 1024k in the 64-bit VM. On x86 Solaris/Linux it is 320k in the 32-bit VM and 1024k in the 64-bit VM.

We can assume that 64-bit Linux is 1m by default.

In addition to JVM Settings, we can manually specify the size of a Thread when creating it:

public Thread(ThreadGroup group, Runnable target, String name , long stackSize)

The size of the stack affects the maximum number of threads, especially in high-traffic servers, where we are often limited by the number of concurrent threads, we need to know where the limit is.

The first is limited to operating systems, in the case of Ubuntu, The/proc/sys/kernel/threads – Max and/proc/sys/vm/max_map_count Defines the total maximum number of threads (Windows has fewer threads in general) and the maximum number of system_calls (mmap).

The second limit, of course, is in the JVM, where the maximum number of threads is the memory we can allocate divided by the memory consumed by a single thread. So for Java processes, given that they are allocated to the heap, stack, and static method area (or perm area), we can generally assume that

Number of threads = (system free memory – heap memory (-xms, -xmx) – perm memory (-xx :MaxPermSize))/thread stack size (-xss)

Note that this is just to help us establish an idea, but there are actually many factors involved.

Another effect of stack size is that StackOverflowError is thrown if a single stack exceeds this size, and recursive calls are common in general.

How do I view the thread stack

The command jstack can be used to list all thread stack descriptions corresponding to the current PID of JVM, including the state of each thread and the method fully qualified name and code position of each stack frame in the stack. Note that this is for readability only, not that these strings are stored in the stack.

Here’s an excerpt from Tomcat’s JStack output:

The JVM memory model article takes you through a snippet of Tomcat’s JStack output

2. Heap and garbage collection

The structure of the heap

For most applications, the Java Heap is the largest chunk of memory managed by the Java virtual machine. The Java heap is an area of memory that is shared by all threads and is created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and almost all object instances are allocated memory here.

The JVM memory model article takes you through generational memory management

First, the heap can be divided into Cenozoic and old age.

The JVM memory model is an article that takes you through the new generation

Then the Cenozoic can be divided into one Eden region and two Survivor regions.

According to the rules, the new object will be allocated in Eden first (if the object is too large, such as a large array, it will be placed directly in the old age). In GC, objects in Eden are moved to survivor until the object reaches a certain age (defined as the number of times it has survived minor GC) and is moved to the old age.

The ratio of Young to Old is 1:2 (this can be specified by the parameter — XX:NewRatio)

By default, Eden: from: to = 8:1:1 (can be set by parameter -xx :SurvivorRatio), that is, Eden = 8/10 of the Cenozoic space size, and from = to = 1/10 of the Cenozoic space size.

Then talk about garbage collection

Heap memory and garbage collection are inseparable topics, and there is a lot of literature on garbage collection, but it is generally confusing, so here I try to show garbage collection from a system perspective.

Garbage collection has freed C++ from manual memory management, manual malloc,free not only increased the complexity of the program, but also increased the number of bugs. Collect by generation. That is, different collection methods were used in the Cenozoic and old generations. In garbage collection, the main goals are: increase system throughput (reduce total garbage collection resource consumption); Reduce The maximum STW (stop-the-world) time; Reduce total STW time. Different systems require different goals to achieve. The generational milestone first greatly reduces STW, and then can be freely combined to achieve the desired goal. Reachability detection reference counting: a garbage collection algorithm used prior to jdk1.2, we need to understand the idea. The main idea is to maintain a counter, and when counter is 0, the object is considered unreferenced and can be reclaimed. The disadvantage is that circular references cannot be handled. ARC (Automatic Reference Counting), a common technology in iOS development, also adopts a similar idea. Should not be used in the current JVM. Root search algorithm: The idea is to traverse the heap from gc root by reference and mark it, called mark. Parallel and single threaded marks will be covered later in the specific collector. The unmarked objects are then recycled, with the benefit of eliminating the “island effect” of circular dependencies. Here gc root refers mainly to: a. object B referenced in the virtual machine stack (local variable table in stack frame). C. Objects referenced by static properties of the class in the method area. D. Object collation policy replication for JNI references in the local method stack: mainly used for generation generation recycling, copying back and forth between the FROM and to sections. A specific structure is required (the current structure of the Young section) to support this. For newly generated objects, frequent copying is the fastest way to find unused objects and reclaim space. So YGC definitely does the most garbage removal in the JVM. Tag cleanup/tag cleanup: Mainly used in old generation recycling, root searches for tags and then removes or cleans unwanted objects. The JVM memory model article takes you through the process of transparent collation

The JVM memory model article takes you through the transparent cleanup process

Here you can see that clearing creates fragmentation space, which is not a good use of memory, but it is not better than clearing, because clearing is slower. CMSGC, for example, uses cleanup rather than collation.

Think about the difference between copy and tag clean/tidy. Why does the new generation use copy? For the new generation, a garbage collection will recycle most objects, so we speed up the collation process by using redundant space (the collation operation of non-redundant space needs to do swap, while the collation operation of redundant space only needs to do move). The “age” of each object can also be recorded to optimize the “promotion” operation so that middle-aged objects are not mistakenly placed in the older age. On the other hand, the old age is more stable. Even if we clear it, there will not be too many fragments, and the cost of sorting will not be too big.

The Serial collector, ParNew collector, Parallel Scavenge collector. Serial Old collector, Parallel Old collector, CMS collector, G1 collector JVM memory model

All of the above garbage collectors have STW, but FGC has a longer STW.

A few highlights of the garbage collectors:

CMSGC:

CMS(Concurrent mark-sweep) is a garbage collector that achieves the shortest collection pause time at the expense of throughput. This garbage collector is ideal for applications that require fast server response, so we call it a low-latency garbage collector. Add -xx :+UseConcMarkSweepGC to the startup JVM parameter. This parameter indicates that CMS is used for older collections. Note that ParNew is used by the new generation by default. The basic algorithm adopted by CMS is: mark – clear.

The JVM memory model article takes you through the transparent MSCGC vs CMSGC

It differs from normal serialized collation (MSC) in that there are three MARK stages (there is actually a pre-cleanup process, but it is ignored without any help in explaining CMSGC). The essence of CMSGC is that because we mark without STW, we get a shorter total STW time. The cost is that parallel mark produces “dirty data”, i.e., objects that need to be marked at the same time, and we have to do STW again and remark.

At the same time, we should note that in getting a shorter STW, we sacrificed system throughput, and the total throughput of CMSGC is lower than that of ParOld.

G1GC

As the latest garbage collector, it has the potential to become the default garbage collector in JDK9.

The main idea is to further divide the old generation into multiple regions, and each GC can target some regions rather than the entire heap. Thus, the maximum single STW time can be reduced at the cost of possibly higher total time.

G1GC makes the system smoother and more stable with slightly lower overall throughput.

In order to compare ParOld,CMSGC, and G1GC, I have attached screenshots from a blog review:

The JVM memory model article takes you through the transparent static method area

Finally, the static method area, also known as Perm Generation. It is used to store information about classes that have been loaded by the virtual machine, constants, static variables, code compiled by the just-in-time compiler, and so on.

Common JVM configurations include:

-XX:MaxPermSize=512m

We sometimes see a Java process report an error like this

Exception in thread “State Saver” java.lang.OutOfMemoryError: PermGen space

This means that we need to adjust the configuration, or there is a bug in the code that causes a large number of perm areas to be occupied, perhaps using too many static variables (map), or using the ASM framework to generate a large number of classes.

The appendix

1. Main parameters of the JVM’s GC log

-xx :+PrintGC Prints GC logs

-xx :+PrintGCDetails Displays GC details logs

-xx :+PrintGCTimeStamps prints GC timestamps (in base time)

-xx :+PrintGCDateStamps Prints the GC timestamp (in the form of a date, e.g. 2013-05-04T21:53:59.234+0800)

-xx :+PrintHeapAtGC Prints heap information before and after GC

– XX: + PrintGCApplicationStoppedTime/GC/output from the pause time

-Xloggc:.. /logs/gc.log Output path of the log file

– XX: + HeapDumpOnOutOfMemoryError / / happen OOM automatic dump stack convenient analysis

2. What about garbage collection strategies

jmap -heap

3. How to see heap memory usage in real time

Jstat -gcutil [pid] [interval] // Displays real-time GC information and memory usage of each generation

Jmap -dump:format=b,file=f1 // Dump memory to binary files

Jmap-histo [pid] // Lists the instance types in memory in reverse order by size

4. Conditions for promotion to the old age: Java engineering, high performance and distributed, high performance, easy to understand. High architecture. Performance tuning, Spring, MyBatis, Netty source analysis and big data and other knowledge points. If you want to get a high salary, want to learn, want to have a good employment prospect, want to compete with others can get an advantage, want to enter Ali interview but worry about the interview, you can come

An object can enter the old region in two ways:

Too many live objects. It’s overflowed in S1 and S2. If it is found that survior cannot be placed when moving from Eden to Survior area, the copy times from Eden to S area will reach a certain number, and the copy will not be recycled and enter old area. (From Eden to Survior1, in reference holding, s1 can not fit the new migrated object, so S1 is cleared, surviving object is promoted to S2; The next time you migrate or continue, you put s2. These objects are copied back and forth from S1 <->s2 a certain number of times and enter Old Gen. This Servivor Space adjusts the appropriate number of survivals Threshold through -xx :MaxTenuringThreshold. But it’s just a suggestion, and ultimately the virtual machine will decide