These look like the symptoms of the problems that G1 has with what are
termed humongous allocations. Briefly: G1 divides the heap into
equal-sized regions, and any allocation that is larger than half of
the size of a region will end up consuming an integer number of full
regions (i.e., if an allocation is for bytes equal to f regions and f
> 0.5 then the allocation will actually consume ceiling(f) regions).
You can think of this as a form of fragmentation. You can verify this
is the case by investigating the GC logs where humongous allocations
are logged (with-XX:+PrintAdaptiveSizePolicy or for more detail add
-XX:+UnlockExperimentalVMOptions
-XX:+G1ReclaimDeadHumongousObjectsAtYoungGC -XX:G1LogLevel=finest
-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC). One way to address
this if you verify this is indeed the case is to increase the region
size so that the humongous allocations are no longer humongous.