1. Objects are allocated in Eden preferentially
-verbose: prints garbage collection information. -xms20m Sets the heap capacity to 20M. -XMx20m Sets the maximum heap capacity to 20M (-xms = -xmx cannot be expanded). -xmn10m Sets the new generation capacity to 10M Print garbage collection details -xx :SurvivorRatio=8 The space ratio of Eden zone to Survivor zone in the new generation is 8:1 -xx :+UseSerialGC uses Serial garbage collector
public class TestAllocation {
public static void main(String[] args) {
int _1MB =1024 * 1024;
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[2 * _1MB];
allocation2 = new byte[2 * _1MB];
allocation3 = new byte[2 * _1MB];
allocation4 = new byte[4 * _1MB];/ / triggers the GC}}Copy the code
The results
[0.068s][info][GC,start] GC(0) Pause Young (Allocation Failure) [0.072s][info][GC,heap] GC(0) DefNew: 7363K->699K(9216K) [0.072s][info][GC,heap] GC(0) Tenured: 0K->6144K(10240K) [0.072s][info][GC,metaspace] GC(0) metaspace: 3840K->3840K(1056768K) [0.072s][info][GC] GC(0) Pause Young (Allocation Failure) 7M->6M(19M) 3.541s ms [0.072s][info ][gc, CPU] gc (0) User=0.00s Sys=0.00s Real=0.00s [0.073s][info][gc,heap, heap, heap, heap, heapexit] Heap [s] 0.073 [info] [gc, Heap,exit] def new generation total 9216K, used 5035K [0x00000000fec00000, 0x00000000ff600000, 0 x00000000ff600000) [s] 0.073 [info] [gc, heap,exit] Eden Space 8192K, 52% used [0x00000000Fec00000, 0x00000000FF03C2F8, 0x00000000FF400000) [0.073s][info][GC,heap,exit] from space 1024K, 68% used [0x00000000FF500000, 0x00000000FF5AECF8, 0x00000000FF600000) [0.073s][info][GC,heap,exit] to space 1024K, 0% used [0x00000000FF400000, 0x00000000FF400000, 0x00000000FF500000) [0.073s][info][GC,heap,exit] tenured generation total 10240K, used 6144K [0x00000000ff600000, 0x0000000100000000, 0 x0000000100000000) [s] 0.073 [info] [gc, heap,exit] the space 10240K, 60% used [0x00000000ff600000, 0x00000000ffc00030, 0x00000000ffc00200, 0 x0000000100000000) [s] 0.073 [info] [gc, heap,exit] Metaspace used 3849K, Capacity 4486K, committed 4864K, reserved 1056768K [0.073s][info][GC,heap,exit ] class space used 345K, capacity 386K, committed 512K, reserved 1048576K
Copy the code
When allocating memory space to ALlocation4, 3*2M has been allocated in Eden, and the free space (2M) is less than 4M. Therefore, the allocation failure triggers the Minor GC. Since allocation1, 2,3 are still alive but not in the Survivor zone, allocation1, 2,3 are transferred to the old zone in advance through the allocation guarantee mechanism. At this time, the memory space of the old zone is occupied by 60%. After the operation is complete, allocation4 can be put into Eden area.
2. Big objects go straight to the old age
VM is set on the basis of the set before increase – XX: PretenureSizeThreshold = 3145728 specifies more than 3 MB objects directly in the old s distribution
public class TestAllocation {
public static void main(String[] args) {
int _1MB =1024 * 1024;
byte[] allocation1;
allocation1 = new byte[4 * _1MB];// If greater than 3MB is allocated directly in the old age}}Copy the code
Running results:
[s] 0.070 [info] [gc, heap,exit] Heap [s] 0.070 [info] [gc, Heap,exit] def new generation total 9216K, used 1384K [0x00000000fec00000, 0x00000000ff600000, 0 x00000000ff600000) [s] 0.070 [info] [gc, heap,exit] Eden Space 8192K, 16% used [0x00000000Fec00000, 0x00000000FeD5A0C0, 0x00000000FF400000) [0.070s][info][GC,heap,exit] from space 1024K, 0% used [0x00000000FF400000, 0x00000000FF400000, 0x00000000FF500000) [0.070s][info][GC,heap,exit] to space 1024K, 0% used [0x00000000FF500000, 0x00000000FF500000, 0x00000000FF600000) [0.070s][info][GC,heap,exit] tenured generation total 10240K, used 4096K [0x00000000ff600000, 0x0000000100000000, 0 x0000000100000000) [s] 0.070 [info] [gc, heap,exit] the space 10240K, 40% used [0x00000000ff600000, 0x00000000ffa00010, 0x00000000ffa00200, 0 x0000000100000000) [s] 0.070 [info] [gc, heap,exit] Metaspace used 3846K, Capacity 4486K, committed 4864K, reserved 1056768K [0.070s][info][GC,heap,exit ] class space used 345K, capacity 386K, committed 512K, reserved 1048576K
Copy the code
The memory space in the old area is 40% occupied.
3. Long-lived objects will enter the old age
-xx :MaxTenuringThreshold=1 When the object age reaches 1, it will enter the old age
public class TestAllocation {
public static void main(String[] args) {
int _1MB =1024 * 1024;
byte[] allocation1, allocation2, allocation3;
allocation1 = new byte[_1MB / 4];
allocation2 = new byte[4 * _1MB];
allocation3 = new byte[4 * _1MB];
allocation3 = null;
allocation3 = new byte[4* _1MB]; }}Copy the code
Running results:
[s] 0.092 [info] [gc, heap,exit] Heap [s] 0.092 [info] [gc, Heap,exit] def new generation total 9216K, used 4334K [0x00000000fec00000, 0x00000000ff600000, 0 x00000000ff600000) [s] 0.092 [info] [gc, heap,exit] Eden Space 8192K, 52% used [0x00000000Fec00000, 0x00000000FF03Bbe0, 0x00000000FF400000) [0.092s][info][GC,heap,exit] from space 1024K, 0% used [0x00000000FF400000, 0x00000000FF400000, 0x00000000FF500000) [0.092s][info][GC,heap,exit] to space 1024K, 0% used [0x00000000FF500000, 0x00000000FF500000, 0x00000000FF600000) [0.092s][info][GC,heap,exit] tenured generation total 10240K, used 5051K [0x00000000ff600000, 0x0000000100000000, 0 x0000000100000000) [s] 0.092 [info] [gc, heap,exit] the space 10240K, 49% used [0x00000000ff600000, 0x00000000ffaeed18, 0x00000000ffaeee00, 0 x0000000100000000) [s] 0.092 [info] [gc, heap,exit] Metaspace used 3854K, Capacity 4486K, committed 4864K, reserved 1056768K [0.092s][info][GC,heap,exit ] class space used 345K, capacity 386K, committed 512K, reserved 1048576K
Copy the code
When the Allocation3 object is created, because the Eden region is less than 4MB, the Minor GC is triggered to transfer allocation1 to the Survivor region and set its object age to 1. -xx :MaxTenuringThreshold=1 specifies that the object will enter the old age when its age reaches 1. Therefore, when allocation3 object is created for the second time, Allocation1 will be transferred to the old age zone and the Survivor zone will be empty.
Adjust -xx :MaxTenuringThreshold=15 (default)
[s] 0.074 [info] [gc, heap,exit] Heap [s] 0.074 [info] [gc, Heap,exit] def new generation total 9216K, used 4334K [0x00000000fec00000, 0x00000000ff600000, 0 x00000000ff600000) [s] 0.074 [info] [gc, heap,exit] Eden Space 8192K, 52% used [0x00000000Fec00000, 0x00000000FF03Bbe0, 0x00000000FF400000) [0.074s][info][GC,heap,exit] from space 1024K, 0% used [0x00000000FF400000, 0x00000000FF400000, 0x00000000FF500000) [0.074s][info][GC,heap,exit] to space 1024K, 0% used [0x00000000FF500000, 0x00000000FF500000, 0x00000000FF600000) [0.074s][info][GC,heap,exit] tenured generation total 10240K, used 5051K [0x00000000ff600000, 0x0000000100000000, 0 x0000000100000000) [s] 0.074 [info] [gc, heap,exit] the space 10240K, 49% used [0x00000000ff600000, 0x00000000ffaeed18, 0x00000000ffaeee00, 0 x0000000100000000) [s] 0.074 [info] [gc, heap,exit] Metaspace used 3851K, Capacity 4486K, committed 4864K, reserved 1056768K [0.074s][info][GC,heap,exit ] class space used 345K, capacity 386K, committed 512K, reserved 1048576K
Copy the code
There is a problem here. Why is the Survivor zone still cleared? Check the problem ↓
public class TestAllocation {
public static void main(String[] args) {
// int _1MB =1024 * 1024;
// byte[] allocation1, allocation2, allocation3;
// allocation1 = new byte[_1MB / 4];
// allocation2 = new byte[4 * _1MB];
// allocation3 = new byte[4 * _1MB];
// allocation3 = null;
// allocation3 = new byte[4 * _1MB];}}Copy the code
Running results:
[s] 0.065 [info] [gc, heap,exit] Heap [s] 0.065 [info] [gc, Heap,exit] def new generation total 9216K, used 1384K [0x00000000fec00000, 0x00000000ff600000, 0 x00000000ff600000) [s] 0.065 [info] [gc, heap,exit] Eden Space 8192K, 16% used [0x00000000Fec00000, 0x00000000FeD5A080, 0x00000000FF400000) [0.065s][info][GC,heap,exit] from space 1024K, 0% used [0x00000000FF400000, 0x00000000FF400000, 0x00000000FF500000) [0.065s][info][GC,heap,exit] to space 1024K, 0% used [0x00000000FF500000, 0x00000000FF500000, 0x00000000FF600000) [0.065s][info][GC,heap,exit] tenured generation total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0 x0000000100000000) [s] 0.065 [info] [gc, heap,exit] the space 10240K, 0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0 x0000000100000000) [s] 0.065 [info] [gc, heap,exit] Metaspace used 3847K, Capacity 4486K, committed 4864K, reserved 1056768K [0.065s][info][GC,heap,exit ] class space used 345K, capacity 386K, committed 512K, reserved 1048576K
Copy the code
In Eden area, 16% of the memory space is still occupied. Part of this memory may be transferred to Survivor space together with ALlocation1. Combined with the dynamic object age determination described below, it is supposed to be this part of memory that causes the above problems.
4. Dynamic object age determination
If the sum of the size of objects of the same age in the Survivor space reaches half of the size of the Survivor space, objects older than or equal to the changed age can enter the old age directly, without waiting until -xx :MaxTenuringThreshold sets the age.
Therefore, the reason for the above problem may be that the extra memory is transferred to Survivor space together with allocation1. Since they are both 1 in age and occupy more than half of Survivor space, they directly enter the old age. So adjusting -xx :MaxTenuringThreshold from 1 to 15 does not work.
5. Space allocation guarantee
Before the Minor COLLECTION, the virtual machine checks whether the maximum available contiguous memory space of the old generation is greater than the total space of all objects of the new generation. If it is greater than this Minor collection, it is safe. Because if the memory required by the new generation of surviving objects after the Minor GC is still greater than the maximum contiguous memory available for the old generation, the allocation guarantee fails and a Full GC must be performed. In JDK6 has Update24 before, you can use – XX: HandlePromotionFailure parameter Settings are receiving assignment guarantees failure, If the receiver receives the data, it may perform Minor GC (before the Minor GC operation, it will compare the average size of the historical allocated guarantee object and the current maximum available continuous memory space in the old age) and then allocate the guarantee successfully, or it may fail to allocate the guarantee and perform Full GC. If not, go straight to Full GC. After JDK6 Update24, this parameter has no effect and fails to receive allocation guarantees by default, avoiding frequent Full GC operations.
This parameter does not affect the operation of the virtual machine.