I have a situation here:
JDK version is showing below:
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
My application is running with default GC strategy with JVM.
Starting by command:
nohup java -jar -Xms512M -Xmx512M -Xmn300M -XX:SurvivorRatio=6 -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:/data/code/logs/application-gc.log -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=/data/code/logs/test-dump -Dspring.profiles.active=test /data/code/application.jar >> /data/code/logs/application.log &
Old generation in JVM will always getting unexpected little objects promoted from young generation and keep old generation usage going up, and then cause a full GC each 4 hours during my test.
Here is the testing code:
@PostMapping("/test/jvmPressure")
public CommonResult jvmTest() {
List<Role> roles = new ArrayList<>();
for (long i = 0L; i < 10000L; i++) {
Role role = new Role();
role.setLevel(1);
role.setParentId(1L);
role.setStatus(true);
role.setName("this is a test object");
role.setRoleName("this is a test object");
role.setCompanyId(123123);
role.setId(i);
roles.add(role);
}
return CommonResult.succeed();
}
I just create a lot of objects and do nothing, to make eden area full and trigger YGC by continuing requesting this API.
Observing by Jmeter, all requests are finished in 15 ms, and I don't think any of the Role
object will suvive to old generation.
But usage of old generation will going up anyway.
Is it possible to figure out what's new to old generation? I cannot find any unusual objects in dump file, and GC log is also quite normal. But still, I'm confused that which object is keep promoting into old generation...
According to my latest observation of Jmeter record and dump file.I have found another strange problem.
The max response time is 2250ms and objects created is 40Mb/s, which means, YGC will trigger every 7s because of the 300M eden space. I thought that many test objects will go into suvive area at the time of YGC triggered, but no test objects would survive more than 2 YGCs. Which means no test objects will go into old generation at all.
But the fact is, when I create dump files after 500 YGCs and find there are lots of unexpected test objects in heap. Before I dump heap, I have shut down Jmeter and waited for 2 YGCs to ensure there are no test objects in young generation, to see if there are test objects promoted to old generation.Unfortunately, it can be seen from this picture that some of the test objects were promoted into old generation in no reason(comparing with a dump file created by same method before).