Heap memory usage analysis, GC log interpretation

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/wjandy0211/article/details/90609384

Heap memory usage analysis, GC log interpretation

Important stuff

  • In Java, object instances are created on the heap. In the method area of ​​some types of information, constants, variables and other static memory. Heap and method area is shared by the threads.
  • GC mechanism is provided by the JVM, used to clean up the object needs to be cleared, the recovery of heap memory.
  • GC mechanism Java programmer freed from memory management, we can focus more on business logic.
  • In Java, GC is known as a daemon thread by a garbage collector to perform.
  • In calls object from an object prior to garbage collection finalize () method.
  • As a Java developer can not force the JVM to perform GC; GC triggered depending on the size determined by the JVM heap memory.
  • System.gc () and Runtime.gc () will be sent to the JVM GC execution request, but does not guarantee the JVM will perform GC.
  • If no memory heap create a new object, and throws an OutOfMemoryError.

What kind of objects can be GC recovery?

  • Before recycling the garbage collector, the first thing is to determine which of these objects still alive and what is dead.

Click to view my other article "in-depth understanding of the Java Virtual Machine" (c) garbage collector and memory allocation strategy

test environment

  • system
    Microsoft Windows [版本 10.0.14393]
    
  • JDK
    java version "1.8.0_112"
    Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
    Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
    
  • test tools
    IntelliJ IDEA 2017.2
    

Sample Code

Here we have to look through a small heap memory analysis program, as follows:

package net.penglei.test;

public class HeapTest {
    private static final int _1M = 1024 * 1024;

    public static void main(String[] args) throws InterruptedException {
        byte[] byte1 = new byte[2 * _1M];
        byte[] byte2 = new byte[2 * _1M];
        byte[] byte3 = new byte[2 * _1M];
        byte[] byte4 = new byte[2 * _1M];
        byte[] byte5 = new byte[2 * _1M];

        byte[] byte6 = new byte[5 * _1M];

        byte[] byte7 = new byte[2 * _1M];


    }
}

Set JVM parameters

-Xms20m
-Xmx20m
-Xmn10m
-verbose:gc
-XX:+PrintGCDetails #输出详细GC日志模式
-XX:+PrintTenuringDistribution #输出每次minor GC后新的存活周期的阈值
-XX:+PrintGCTimeStamps #输出gc的触发时间

My IntelliJ IDEA configuration

View program process, heap details

  • Check  jps -l to see the process through  jmap -heap pid  to view the summary of the heap
$ jps -l
5636 net.penglei.test.HeapTest

Heap Configuration

$ jmap -heap 5636

Attaching to process ID 5636, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.112-b15

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration: 
   MinHeapFreeRatio         = 0                
   MaxHeapFreeRatio         = 100 		#GC后如果发现空闲堆内存占到整个预估堆内存的N%(百分比)  
   MaxHeapSize              = 20971520 (20.0MB)	# 堆最大空闲    jvm参数 -Xms20m
   NewSize                  = 10485760 (10.0MB)	# 年轻代空间    jvm参数 -Xmn10m
   MaxNewSize               = 10485760 (10.0MB)	# 年轻代最大空间
   OldSize                  = 10485760 (10.0MB)	# 老年代空间 =(等于)堆内存大小 -(减去)年轻代大小
   NewRatio                 = 2   
   SurvivorRatio            = 8   # 年轻代内存又被分成三部分 Eden 空间 80% 而From Survivor 空间 和 To Survivor空间 分别占用10%
   MetaspaceSize            = 21807104 (20.796875MB) # 设置元空间的最大值 jvm参数 -XX:MaxMetaspaceSize
   CompressedClassSpaceSize = 1073741824 (1024.0MB)  # 类指针压缩空间大小, 默认为1G
   MaxMetaspaceSize         = 17592186044415 MB    # 是分配给类元数据空间的最大值
   G1HeapRegionSize         = 0 (0.0MB) # G1区块的大小, 取值为1M至32M. 其取值是要根据最小Heap大小划分出2048个区块

...

Executing the byte3

byte[] byte3 = new byte[2 * _1M];
$ jmap -heap 5636
...
Heap Usage:
PS Young Generation
Eden Space:
   capacity = 8388608 (8.0MB)
   used     = 7635080 (7.281379699707031MB)
   free     = 753528 (0.7186203002929688MB)
   91.01724624633789% used
From Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
To Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
PS Old Generation
   capacity = 10485760 (10.0MB)
   used     = 0 (0.0MB)
   free     = 10485760 (10.0MB)
   0.0% used

1628 interned Strings occupying 148560 bytes.
Data block The total capacity of the heap Use Capacity The remaining capacity The use of accounting
The young generation 8.0MB 7.28MB 0.71MB 91.0%
Survivors 0 1.0MB 0.00MB 1.0MB 0.0%
Survivors 1 1.0MB 0.00MB 1.0MB 0.0%
Years old 10.0MB 0.00MB 10.MB 0.0%

A brief summary

  • PS Young Generation the young generation space usage reaches 91.0%, remaining memory 0.71MB, when the next execution byte4 (2M memory occupied by the young generation), will trigger Eden Space space (the young generation) Minor GC (the young generation garbage collection).

  • PS Old Generation's old space usage reaches 0.00%, remaining memory 10.MB, when the next execution byte4 (2M memory occupied by the young generation), above Eden Space space (the young generation) Minor GC (the young generation garbage collection), will grow old s occupation of part of the memory.

Executing the byte4

byte[] byte4 = new byte[2 * _1M]

GC console log print

641.638: [GC (Allocation Failure) 
Desired survivor size 1048576 bytes, new threshold 7 (max 15)
[PSYoungGen: 7456K->728K(9216K)] 7456K->6880K(19456K), 0.0036244 secs] 
[Times: user=0.00 sys=0.00, real=0.00 secs] 


641.642: [Full GC (Ergonomics) 
[PSYoungGen: 728K->0K(9216K)] [ParOldGen: 6152K->6700K(10240K)] 6880K->6700K(19456K), 
[Metaspace: 2848K->2848K(1056768K)], 0.0068164 secs] 
[Times: user=0.00 sys=0.00, real=0.01 secs] 

GC log block diagram ps (not drawn)

$ jmap -heap 5636
...
Heap Usage:
PS Young Generation
Eden Space:
   capacity = 8388608 (8.0MB)
   used     = 2097168 (2.0000152587890625MB)
   free     = 6291440 (5.9999847412109375MB)
   25.00019073486328% used
From Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
To Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
PS Old Generation
   capacity = 10485760 (10.0MB)
   used     = 6861768 (6.543891906738281MB)
   free     = 3623992 (3.4561080932617188MB)
   65.43891906738281% used

1556 interned Strings occupying 143760 bytes.

GC logs detailed analysis

641.638: [GC (Allocation Failure) 
Desired survivor size 1048576 bytes, new threshold 7 (max 15)
[PSYoungGen: 7456K->728K(9216K)] 7456K->6880K(19456K), 0.0036244 secs] 
[Times: user=0.00 sys=0.00, real=0.00 secs] 

Parallel Scavenge GC younger generation of collectors

641.638: [GC (Allocation Failure)
  • 1641.638: GC is the time of this occurrence, from the start jvm since the beginning of time, in seconds. This is the time Minor GC(the young generation garbage collection), Minor GC is very frequent, fast recovery speed.
Desired survivor size 1048576 bytes, new threshold 7 (max 15)
  • The desired size of 1048576 bytes survivors, the survival period of the new threshold value of 7 (max 15).
[PSYoungGen: 7456K->728K(9216K)]

Format: [PSYoungGen: a-> b (c)]

The young generation is the use of multi-threaded garbage collector  Parallel Scavenge(the new generation of collectors, the general multi-threaded copying collector algorithms, parallel)

  • PSYoungGen, represents the GC occurs in younger generations.
  • a GC before the young generation has to take up space, the young generation is subdivided into a space and Eden From Survivor To Survivor space and space.
  • b After Minor GC to GC after Eden space the young generation space or space occupied Survivor has been occupied.
  • c c parentheses indicates the size of the entire young generation.
7456K->6880K(19456K)

Format: x-> y (z)

  • x represents the occupied space in front of the GC heap,
  • After y represents the GC heap occupied space,
  • z represents the total size of the heap.
, 0.0036244 secs]
  • The GC represents the time consumed.
[Times: user=0.00 sys=0.00, real=0.00 secs]
  • And to provide use of cpu time consuming, user is the user mode cpu time consumed, sys is the system state cpu time consumed, real time actual consumption.

Years old take up memory space calculation

  • Old age memory size = (equals) heap memory size - (minus) the young generation of memory size.
  • This embodiment is 19456K - 9216K = 10240K

Parallel Old is old Parallel Scavenge collector's edition

641.642: [Full GC (Ergonomics) 
[PSYoungGen: 728K->0K(9216K)] [ParOldGen: 6152K->6700K(10240K)] 6880K->6700K(19456K), 
[Metaspace: 2848K->2848K(1056768K)], 0.0068164 secs] 
[Times: user=0.00 sys=0.00, real=0.01 secs] 
641.642: [Full GC (Ergonomics)

GC years old, also known as Major GC, often accompanied by a Minor GC (the young generation garbage collection) is slower

  • 641.642: The GC is the time of occurrence, from the start jvm since the beginning of time, in seconds. [Full GC (Ergonomics), that the implementation of the global garbage collection
[PSYoungGen: 728K->0K(9216K)]

Format: [PSYoungGen: a-> b (c)]

The young generation is the use of multi-threaded garbage collector  Parallel Scavenge(the new generation of collectors, the general multi-threaded copying collector algorithms, parallel)

  • PSYoungGen, represents the GC occurs in younger generations.
  • a GC before the young generation has to take up space, the young generation is subdivided into a space and Eden From Survivor To Survivor space and space.
  • b After Minor GC to GC after Eden space the young generation space or space occupied Survivor has been occupied.
  • c c parentheses indicates the size of the entire young generation.
[ParOldGen: 6152K->6700K(10240K)]

Format: [ParOldGen: x-> y (z)]

Old's GC, using the Parallel Old collectors, is an old Parallel Scavenge collector's edition, a move multithreading and "mark - finishing" algorithm

  • ParOldGen represent GC occurred in the old era.
  • x is the old GC's former space occupied
  • y is the old GC's occupied space
  • Z brackets for the size of the entire old age
6880K->6700K(19456K)

Format: e-> f (g)]

  • e piles before the GC memory footprint,
  • f piles after GC memory footprint,
  • Brackets g total size of the entire JVM heap.
[Metaspace: 2848K->2848K(1056768K)]

java8 characteristic is the generation of a permanent (Permanent Generation (PermGen)) transplanted into the voxel space (Metaspace)

The format is:t->y(u)]

JDK8 HotSpot JVM uses local memory to store data information and call classifier: element space (Metaspace); and that the Oracle JRockit IBM JVM 'is very similar. This will be good news: it means that there will be no java.lang.OutOfMemoryError: PermGenproblem

By default, the local class metadata only by available memory limit (depending on the capacity of a 32-bit or 64-bit operating system available virtual memory size)

  • t is a former garbage collection element space memory footprint
  • y after garbage collection element space memory footprint
  • Brackets u-dimensional space for the JVM memory size
, 0.0068164 secs]
  • The GC represents the time consumed.
[Times: user=0.00 sys=0.00, real=0.01 secs]

Providing cpu usage and time consuming

  • user: user mode as used cpu time consumed
  • sys: system state is the cpu time consumed
  • real: The GC is the actual elapsed time
Data block The total capacity of the heap Use Capacity The remaining capacity The use of accounting
The young generation 8.0MB 2.00MB 5.99MB 25.0%
Survivors 0 1.0MB 0.00MB 1.00MB 0.0%
Survivors 1 1.0MB 0.00MB 1.00MB 0.0%
Years old 10.0MB 6.54MB 3.45MB 65.4%

A brief summary

  • The young generation Eden Space space usage reaches 25.0%, remaining memory 5.99MB, when the next execution byte5 (2M memory occupied by the young generation) do not trigger the young generation Eden Space space Minor GC (the young generation garbage collection).

  • Old's space usage reaches 6.54%, remaining memory 3.45MB, when the next execution byte5 (2M memory occupied by the young generation), will not trigger old's space Major GC (garbage collection years old), because the young generation has enough space.

Executing the byte5

byte[] byte5 = new byte[2 * _1M];
$ jmap -heap 5636
...
Heap Usage:
PS Young Generation
Eden Space:
   capacity = 8388608 (8.0MB)
   used     = 4356568 (4.154747009277344MB)
   free     = 4032040 (3.8452529907226562MB)
   51.9343376159668% used
From Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
To Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
PS Old Generation
   capacity = 10485760 (10.0MB)
   used     = 6861768 (6.543891906738281MB)
   free     = 3623992 (3.4561080932617188MB)
   65.43891906738281% used

1556 interned Strings occupying 143760 bytes.

Data block The total capacity of the heap Use Capacity The remaining capacity The use of accounting
The young generation 8.0MB 4.15MB 3.84MB 51.9%
Survivors 0 1.0MB 0.00MB 1.00MB 0.0%
Survivors 1 1.0MB 0.00MB 1.00MB 0.0%
Years old 10.0MB 6.54MB 3.45MB 65.4%

A brief summary

  • The young generation Eden Space space usage reaches 51.9%, remaining memory 3.84MB, when the next execution byte6 (5M memory occupied by the young generation), resulting in the young generation space is not enough, will trigger the young generation Eden Space space Minor GC (the young generation garbage collect), to divert a portion of memory to PS old Generation years old.

  • PS Old Generation space old time, usage reaches 6.54%, remaining memory 3.45MB, when the next execution byte6 (occupied by the young generation 5M memory), because the young generation part of the memory and transferred to the old era, leading to old's space is not enough, triggers old's PS old Generation space Major GC (old's garbage collection).

Executing the byte6

byte[] byte6 = new byte[5 * _1M];

GC console log print

10342.704: [

Full GC (Ergonomics) 

		 [PSYoungGen: 4254K->2048K(9216K)] 
		 [ParOldGen: 6700K->8745K(10240K)]
		 10955K->10793K(19456K), 
		 [Metaspace: 2848K->2848K(1056768K)],

 0.0154383 secs
 ] 

[Times: user=0.00 sys=0.03, real=0.02 secs] 

The GC logs detailed interpretation, please refer to the interpretation above, after executing byte4 log ps (that interpretation in more detail)

  • This is the fact, that the log is: before and after the young generation G recovered around old's recovery GC, GC before and after the recovery of the entire heap, the original data space before and after the recovery, memory usage. GC three blocks of memory consumed by the recovery time, and time consuming to provide the use of cpu time

Simple interpretation of GC logs

  • PS Young Generation Young Generation Eden Space space usage reaches 4254K, when executed byte6 (occupied by the young generation 5M memory), resulting in the young generation space is not enough, will first trigger the young generation Eden Space space Minor GC (the young generation garbage collection), to transfer a portion of memory to PS old Generation years old, after GC reclaim Eden space space remaining 2048K.

  • PS Old Generation old's space usage reaches 6700K, when executed byte6 (occupied by the young generation 5M memory), as part of the young generation of memory and transferred to the old era, leading to old's space is not enough, will first trigger old's PS Old Generation space Major GC (old's garbage collection). After recovering Eden Space GC remaining space 8745K.

$ jmap -heap 5636
...
Heap Usage:
PS Young Generation
Eden Space:
   capacity = 8388608 (8.0MB)
   used     = 7507856 (7.1600494384765625MB)
   free     = 880752 (0.8399505615234375MB)
   89.50061798095703% used
From Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
To Space:
   capacity = 1048576 (1.0MB)
   used     = 0 (0.0MB)
   free     = 1048576 (1.0MB)
   0.0% used
PS Old Generation
   capacity = 10485760 (10.0MB)
   used     = 8955872 (8.540985107421875MB)
   free     = 1529888 (1.459014892578125MB)
   85.40985107421875% used

1556 interned Strings occupying 143760 bytes.

Data block The total capacity of the heap Use Capacity The remaining capacity The use of accounting
The young generation 8.0MB 7.16MB 0.83MB 89.5%
Survivors 0 1.0MB 0.00MB 1.00MB 0.0%
Survivors 1 1.0MB 0.00MB 1.00MB 0.0%
Years old 10.0MB 8.54MB 1.45MB 85.4%

Executing the byte7

byte[] byte7 = new byte[2 * _1M];

A brief summary

  • After the reference byte6 execution, PS Young Generation Young Generation Eden Space space usage reaches 89.5%, remaining memory 0.83MB, execution byte7 (2M memory occupied by the young generation), resulting in the young generation space is not enough, it will trigger Eden Space space (Young Generation) Minor GC (the young generation garbage collection)
  • After the reference byte6 execution, PS Old Generation's old space usage reaches 85.4%, remaining memory 1.45MB, execution byte7 (2M memory occupied by the young generation), will lead the young generation GC recycling into the old era, but also bear years old No, will  OutOfMemoryError.

GC console log print

10427.298: [Full GC (Ergonomics) [PSYoungGen: 7331K->7168K(9216K)] [ParOldGen: 8745K->8745K(10240K)] 16077K->15913K(19456K), [Metaspace: 2849K->2849K(1056768K)], 0.0065366 secs] [Times: user=0.09 sys=0.02, real=0.01 secs] 

10427.305: [Full GC (Allocation Failure) [PSYoungGen: 7168K->7168K(9216K)] [ParOldGen: 8745K->8745K(10240K)] 15913K->15913K(19456K), [Metaspace: 2849K->2849K(1056768K)], 0.0027873 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Heap
	at net.penglei.test.HeapTest.main(HeapTest.java:16)
 PSYoungGen      total 9216K, used 7462K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 91% used [0x00000000ff600000,0x00000000ffd49b60,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 8745K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 85% used [0x00000000fec00000,0x00000000ff48a708,0x00000000ff600000)
 Metaspace       used 2880K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 309K, capacity 386K, committed 512K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:59679', transport: 'socket'

Process finished with exit code 1 。
[Full GC (Ergonomics) [PSYoungGen: 7331K->7168K(9216K)]
  • The Minor GC PS Young Generation occur in the young generation Eden Space space, because the old year had 85.4% occupancy, the old year is not enough, this time the young generation garbage collection is not much action, only recovered a Diudiu.
[ParOldGen: 8745K->8745K(10240K)]
  • The Major GC occurs in PS Old Generation years old, because the old era and occupied 85.4%, with recovery not enough space, resulting in no effect on the recovery years old **
16077K->15913K(19456K)

These are telling you, in front of the heap occupancy before memory overflow Exception

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Heap
	at net.penglei.test.HeapTest.main(HeapTest.java:16)
 PSYoungGen      total 9216K, used 7462K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 91% used [0x00000000ff600000,0x00000000ffd49b60,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 8745K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 85% used [0x00000000fec00000,0x00000000ff48a708,0x00000000ff600000)
 Metaspace       used 2880K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 309K, capacity 386K, committed 512K, reserved 1048576K
  • PS at the moment before the young generation Generation JVM heap recovered Young occupation 16077K, after the young generation JVM heap is reclaimed 16077K, 19456K the total size of the JVM heap
[Full GC (Allocation Failure)
[PSYoungGen: 7168K->7168K(9216K)] [ParOldGen: 8745K->8745K(10240K)] 15913K->15913K(19456K)
  • PSYoungGen the young generation Minor GC, ParOldGen old's Major GC years old can not bear 15913K memory, then the overflow on the heap memory OutOfMemoryError

  • Why's this old to bear 15913K memory? Full GC because the first two were unsuccessful, resulting in a backlog of some heap memory space, heap natural fit, and then to put years old, years old does not fit on a heap overflow

Summary memory allocation and recovery strategies

  • Objects priority allocation in the new generation

  • Large objects directly into the old year

  • Long-term survival of the object will enter the old year

  • Age dynamic object determination: If Survivor space of the same age greater than half the total size of all objects in space Survivor, greater than or equal to the subject's age directly into the old.

  • Space allocation guarantees: Before Minor GC occurs, the virtual machine to check whether the maximum old's available contiguous space larger than the new generation of all objects in the total space, if not established, the virtual view HandlePromotionFailure settings whether to allow a security failure, if allowed to continue checking old's maximum available whether continuous space than the previous promotion to the average size of old age, if more than attempts to conduct a Minor GC; if less than or allowed to take risks, will conduct a Full GC.

Objects in eden 1 priority allocation

In most cases, the object priority in the allocation of the new generation in the Eden area. When the Eden area is not enough space, the virtual machine will launch a Minor GC. Minor GC and Full GC.

  • Minor GC: the new generation GC, very frequent, fast recovery speed.
  • Fulll GC: old's GC, also known as Major GC, often accompanied by a Minor GC, slower.

2 large objects directly into the old year

  • Large objects are Java objects requires a lot of contiguous memory space, the most typical of large objects is the kind of long strings and arrays.

  • Virtual machines provide a parameter: PretenureSizeThresholdgreater than this parameter object will be allocated directly in the old era.

3 long-lived objects will enter the old year

  • Virtual machine for each object defines a target age counter (Age), still alive after the object each time through the Minor GC, Survivor and can be accommodated, then aged just +1, when aged to a certain extent (the default is 15), will be promoted to the old era, this threshold parameters can  MaxTenuringThreshold be set.

4. The moving object determination age

4 dynamic target age determination

  • If the sum of the same age Survivor space is larger than half the size of all the objects in space Survivor, age greater than or equal to the object that age you can go directly to the old era.

5 space allocation guarantees

  • In order to better adapt to the different procedures of memory condition, age is not an object must reach a threshold before entering the old era.
  • The average size of the contiguous space as long as the new generation of old age is greater than the total size of the object or the previous promotion will be Minor GC, otherwise it will be Full GC.

Guess you like

Origin blog.csdn.net/wjandy0211/article/details/90609384