When the heap is almost full, the GC spends more of its time looking at and copying objects which are kept than finding objects to remove.
Say you can have 1 million objects in your system and you are 10 % full, this means 10% need be examined and you will have 90% free afterwards given you a long time before the next GC.
Say you have have a system which is 90% full, this means 9x as many objects need to be examined (taking 9x longer) and only 10% will be freed giving you little time before the next GC is required. If your program is creating objects at the same time, you can fill the freed memory as fast as it is freed and you will be constantly GCing.
I agree with your point no issues with that.
But here is my doubt. Scenario what I explained why not JVM expand its heap. Because its not reached to its maximum. I understand GC is busy collecting data, but it may or may not be able to collect or there is nothing to collect. So my only point why not JVM grow. Even after when it reached its maximum if it could'nt make any room for new objects in that scenario if its fails with OOM then there is no issue. That point of time we can say see we have any leaks in app or the app might need more memory.