I thought this problem was solved decades ago? Doesn't Java have a well-tuned generational garbage collector that can handle this?
.Net was hyper-optimized for this over a decade ago with its 3-generation system, where the 0th generation allowed for extremely rapid allocation and collections. I thought Java had similar capabilities?
(Summary, which BTW is probably outdated)
0 generation: Pre-allocate a continuous chunk of RAM. Every allocation goes to the next bytes of the chunk. When there's no more free RAM left, find all reachable objects in the 0 generation and copy them to the 1 generation.
1 generation: Works the same as the 0 generation, except it's larger and objects are copied to the 2 generation.
2 generation: Garbage collections here are traditional "mark and sweep" collections.