Understanding GC Logs
Let’s look at the code example of yesterday’s object saving itself
VM args:-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
Copy the code
We’re talking about one paragraph at a time
2019-12-11T14:38:51.807+0800(GC time +0800): 0.180(GC time +0800): [GC(GC stands for Young GC,Full GC is itself)(system.gc ()) (trigger GC, in this case because system.gc () was called))) [Times: 1424k -> 1424k] [Times: 1424k -> 1424k] [Times: 1424k -> 1424k] [Times: 1424k -> 1424k] User =0.00(CPU time) sys=0.00(CPU time), real=0.00 [2019-12-11t14:38:51.809 + 0800:0.181: [Full GC (System.gc()) [PSYoungGen: 1419K->0K(76288K)] [ParOldGen: 8K->1182K(175104K)] 1427K->1182K(251392K), [Metaspace: 3134K->3134K(1056768K)], 0.0049875secs] [Times: User =0.00 sys=0.00, real=0.00 Complete self redemption! I'm alive! 2019-12-11T14:39:01.816+ 0800:10.188: [GC (system.gc ())] [PSYoungGen: [Times: Times: 328k -> 328K] 328K -> 328k [Times: 328k -> 328k] 328K -> 328k [Times: 328k] Sys =0.00, real=0.00 secs] 2019-12-11t14:39:01.817 + 0800:10.817: [sysgc ())] [PSYoungGen: 592K->0K(76288K)] [ParOldGen: 1190K->1318K(175104K)] 1782K->1318K(251392K), [Metaspace: [Times: user= 0.03sys =0.00, real= 0.03secs] [Times: user= 0.03sys =0.00, real= 0.03secs] Heap PSYoungGen total 76288K, used 3058K [0x000000076b180000, 0x0000000770680000, 0x00000007c0000000) eden space 65536K, 4%, informs [x000000076b180000 0, 0 x000000076b47cb08, 0 x000000076f180000) from space 10752 k, 0% informs [0 x000000076fc00000, 0 x000000076fc00000, 0 x0000000770680000) to space 10752 k, 0% informs [x000000076 x000000076f180000 0, 0 x000000076f180000, 0fc00000) ParOldGen total 175104K, used 1318K [0x00000006c1400000, 0x00000006cbf00000, 0x000000076b180000) object space 175104K, 0%, informs [x00000006c1400000 0, 0 x00000006c1549bf0, 0 x00000006cbf00000) Metaspace informs the 3789 k, capacity 4540 k, committed 4864K, reserved 1056768K class space used 413K, capacity 428K, committed 512K, reserved 1048576KCopy the code
- Young GC
- Full GC
-
Garbage collector parameters Summary (long-term update)
parameter | describe |
---|---|
UseSerialGC | Default value for VMS running in Client mode. After this function is enabled, the Serial and Serial Old collectors are used to reclaim memory |
UseParNewGC | When this switch is turned on, the collector combination of ParNew + Serial Old is used for memory reclamation |
UseConcMarkSweepGC | When this switch is turned on, the collector combination of ParNew+ CMS + Serial Old is used for memory reclamation. The Serial Old collector will be used as a fallback collector in the event of Concurrent Mode Failure of the CMS collector |
UseParallelGC | The vm operates in Server mode by default. Use the Parallel Scavenge + Serial Old (PS Mark Sweep) collector to reclaim memory |
UserParallelOldGC | When this switch is turned on, recycle memory using a combination of the Parallel Avenge + Parallel Old collector |
SurvivorRatio | Capacity ratio between Eden region and Survivor region in the new generation. The default value is 8, indicating Eden: Survivor = 8:1 |
PretenureSizeThreshold | Directly to the size of the object in the old age. If this parameter is set, objects larger than this parameter will be directly allocated in the old age |
MaxTenuringThreshold | Promotion to the target age of the older age. After each Minor GC, the age of each object increases by 1, and when this parameter value is exceeded, the object enters the old age |
UseAdaptiveSizePolicy | Dynamically adjusts the size of the various regions in the Java heap and the age into the old age |
HandlePromotionFailure | Whether to allow the allocation guarantee to fail, that is, the remaining space of the old generation is not enough to cope with the extreme case that all objects in the whole Eden and Survivor zone of the new generation survive. After JDK6, this parameter will be invalid |
ParallelGCThreads | Sets the number of threads to recycle in parallel GC |
GCTimeRatio | The ratio of GC time to total time. The default value is 99, which allows 1% of GC time. Only valid when using the Parallel Scavenge collector |
MaxGCPauseMillis | Set the maximum pause time for GC. Only valid when using the Parallel Scavenge collector |
CMSInitiatingOccupancyFraction | Sets the CMS collector to trigger garbage collection after the old time has been used. The default value is 68% and only takes effect when the CMS collector is used |
UseCMSCompactAtFullCollection | Sets whether the CMS collector should perform a memory defragmentation after garbage collection is complete. Only valid when using the CMS collector |
CMSFullGCsBeforeCompaction | Setting the CMS collector to start memory defragmentation after several garbage collections only takes effect when the CMS collector is in use |
-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m | Set the initial size and maximum size of the meta-space |
-Xmx20m -Xms10m | Maximum heap space, initial heap space |
-XX:MaxDirectMemorySize=10M | Maximum direct memory space |
-XX:+PrintGC | Outputting GC Logs |
-XX:+PrintGCDetails | Prints verbose logs for GC |
-XX:+PrintGCTimeStamps | The timestamp of the output GC (in the form of base time) is the time since JVM startup |
-XX:+PrintGCDateStamps | The output GC timestamp (in the form of a date, for example, 2013-05-04T21:53:59.234+0800) is the initial GC execution time |
-Xss128k | The stack depth |
-Xmn | Cenozoic size |
-XX:+/-UseTLAB | Set whether the JVM uses TLAB |
-XX:+printFlagsFinal | View the parameter defaults |
-XX:+HeapDumpOnOutOfMemoryError | OOM generate dump |
-XX:+HeapDumpOnCtrlBreak | Hold CTRL + break to generate dump |
-XX:MaxDirectMemorySize | Direct memory size |
-XX:+DisableExpicitGC | Disallow manual system.gc () |
-XX:+AlwaysTenure | Indicates that there are no surviving zones and all objects will be promoted to the old age on the first GC |
-XX:+PrintGCApplicationStoppedTime | Prints the time the program is paused during garbage collection. Can be mixed with the above |
-Xloggc:gc.log | Output gCLOg in the same directory |
-XX:+PrintReferenceGC | It is used to trace soft references, weak references, and virtual references in the system, and display the reference process |
Memory allocation and reclamation policies
Automatic memory management in Java ultimately boils down to two things: automatically allocating memory to objects and reclaiming memory from objects
Object allocation
Memory allocation for objects, in general, is heap allocation, mainly in the Eden region of the new generation. If local thread caching is enabled, it will be allocated on the TLAB first, or in rare cases directly to the old generation, depending on which collector is used and which JVM parameters are set
TLAB (Thread local allocation Buffer (-xx :+/ -usetlab) specifies that each thread preallocates a small chunk of memory in the Java heap. If the thread needs to allocate memory, it allocates it on the TLAB of the thread. If the TLAB is used up and a new TLAB is allocated, the synchronization lock is required
In most cases, objects are allocated in Eden of the new generation. When Eden does not have enough space to allocate, the virtual machine will initiate a Minor GC
MinorGC, or YoungGC, happens in the new generation of GC because most Java objects live and die. So MinorGC is very frequent and generally very fast
FullGC occurs in old GC and is usually accompanied by at least one MinorGC, which is generally more than 10 times slower than MinorGC
package com.practice.JVM.ObjectAllocation;
/ * * *@author zhaoxu
* @version 1.0
* @className EdenToOld
* @descriptionThere is not enough space in Eden, so it is guaranteed by the old age@date 2019/12/11 15:59
* vm args -XX:+UseSerialGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8
**/
public class EdenToOld {
private static final int _1MB = 1024*1024;
public static void main(String[] args) {
// Maintain 1 Byte array containing 1024*1024 Byte elements, of course 1MB
// Byte[] allocation1 = new Byte[2 * _1MB];
// Byte[] allocation2 = new Byte[4 * _1MB];
// Byte[] allocation3 = new Byte[6 * _1MB];
Byte[] allocation1 = new Byte[2 * _1MB];
Byte[] allocation2 = new Byte[2 * _1MB];
Byte[] allocation3 = new Byte[2 * _1MB];
Byte[] allocation4 = new Byte[4 * _1MB];
}
}
print
2019-12-11T16:33:39.897+0800: 0.170: [GC (Allocation Failure) 2019-12-11T16:33:39.897+0800: 0.170: [DefNew: 5188K->1024K(9216K), 0.0015865 secs]2019-12-11T16:33:39.898+0800: 0.171: [Tenured: 8357K->9380K(10240K), 0.0043435 secs] 13380K->9380K(19456K), [Metaspace: 3195K->3195K(1056768K)], 0.0059865 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
2019-12-11T16:33:39.903+0800: 0.176: [Full GC (Allocation Failure)The 2019-12-11 T16:33:39. 903 + 0800:0.176: [Tenured: 9380 k - > 9332K(10240K), 0.0037593 secs] 9380 - > 9332 kK(19456K), [Metaspace: 3195K->3195K(1056768K)], 0.0037828 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.practice.JVM.ObjectAllocation.EdenToOld.main(EdenToOld.java:21)
Heap
def new generation total 9216K, used 330K [0x00000000fec00000.0x00000000ff600000.0x00000000ff600000)
eden space 8192K, 4% used [0x00000000fec00000.0x00000000fec52ac0.0x00000000ff400000)
from space 1024K, 0% used [0x00000000ff500000.0x00000000ff500000.0x00000000ff600000)
to space 1024K, 0% used [0x00000000ff400000.0x00000000ff400000.0x00000000ff500000)
tenured generation total 10240K, used 9332K [0x00000000ff600000.0x0000000100000000.0x0000000100000000)
the space 10240K, 91% used [0x00000000ff600000.0x00000000fff1d2c0.0x00000000fff1d400.0x0000000100000000)
Metaspace used 3285K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 353K.capacity 388K.committed 512K.reserved 1048576K
Process finished with exit code 1
Copy the code
The result of the program is completely different from the book, I use Serial collector, I do not know what is taking up a lot of memory space
Big object goes straight to the old age
Large object refers to Java objects that need a lot of consecutive memory space, the most typical is the kind of a long string and array use – XX: PretenureSizeThreshold = 111 b, to make large objects helicopters and old age Note: this parameter applies only to Serial and ParNew, PS don’t know
Long-term survival into the old age
The virtual machine defines an Age counter for each object. When the object is born in Eden and passes a minorGC, the Age is +1 for each minorGC passed by Survivor. The default parameter -xx :MaxTenuringThreshold=15. An object in Survivor with an age of 1 enters the old age in the next GC
Dynamic object age determination
To better adapt to different situations, virtual machines do not always require that the age of objects must reach MaxTenuringThreshold. If the total size of all objects of the same age in a Survivor space is greater than half of that in a Survivor space, objects older than or equal to this age can directly enter the old age
For example, if the total size of Survivor area is 1024KB, two 300KB objects with ages of 2 can be copied to the old Age. If only one of them is 2, it will not be copied to the old Age
Space allocation guarantee
Before MinorGC occurs, the JVM checks to see if the maximum available continuous space of the old age is greater than the total space of all objects of the new generation. If this condition is true, the MinorGC is safe even in extreme cases (all objects of the new generation survive)
If this is not true, the JVM looks at the HandlePromotionFailure setting to see if the guarantee is allowed to fail. If this is allowed, the JVM continues to check if the maximum contiguity available in the old age is greater than the average size of objects promoted to the old age over time If it is, try a minorGC, even though the GC is risky. If it succeeds, it succeeds, and if it fails, a FullGC is launched after the failure
If less than, or risk is not allowed, then change to FullGC once
Although the circle of guarantee failures is the largest, guarantee failures are allowed in most cases to avoid too frequent FullGC
After JDK6, this parameter is invalid
The current rule is that MinorGC will be performed as long as the old continuous space is greater than the total size of the new generation object or the average total size of the previous promotions, otherwise FullGC will be performed.