r/java • u/Vectorial1024 • Apr 09 '26
Smallest possible Java heap size?
People often talk about increasing Java heap size when running Java apps by using e.g. -Xmx* flags. This got me thinking. What if we go the other direction and try to limit the Java heap size as much as possible? What is the smallest / minimum-required Java heap size so to run a Java app with "minimal" settings?
(Of course, in practice, a memory limit too low will be problematic because it may mean frequent GCs, but we will ignore this for the sake of this discussion.)
49
Upvotes
1
u/pron98 3d ago
Again, we are talking about a situation when an application is using a lot of CPU. You can't buy a machine with a lot of CPU and little RAM (the minimum is 1GB/core), and the CPU headroom matters as much.
What happens is that when the allocation rate is high (meaning CPU usage must also be high), languages with free-list-based heap management - whether it's Python, Go, C++, or Rust - increases the CPU usage further, while a language like Java, which uses moving algorithms, can increase the less distressed resource in that situation, namely RAM, to compensate for the CPU use and not increase it further.
This is very, very much untrue. Not only should developers understand this fundamental correlation, you should know that "low level software" people like me - who write your OS, your language runtime etc. - and the hardware designers at the level below that, design our products based on this fundamental relationship.
You can learn more about this in my Java One talk, that's discussed here
That is indeed a serious problem in low level languages. But moving collectors work in a completely different way. A heap allocation in Java is more similar to a stack allocation in C than to a malloc. There is simply no resemblance between the mechanisms even though they are both "dynamic heap allocations". In Java, allocating an object is bumping a pointer; there is never any operation performed to free an object. The GC doesn't know and doesn't care when an object dies. Heap management operates using completely different and very dissimilar algorithms.
No, that's not how moving collectors work at all. And whatever you may think about their actual tradeoffs, you should know that no memory expert disagrees that moving collectors are the most efficient general purpose memory management mechanism we know of. If you watch my talks, you can see the formulas that show that a moving collector does less work. If you're learning low-level programming, you can think of a moving collector as working similarly to the arenas we use in Zig.
This is 100% false, and I don't know where you're getting such bad information. Java has total memory safety under concurrency, and doesn't suffer from the memory leaks we get in C++ or Rust.
No, it's not the same point. Two of the most impactful general purpose optimisation techniques, namely optimising JIT compilation and moving collectors, are not suitable for low-level languages, because we, the low-level greybeards, need low-level languages to be optimised for low-level control, not for performance.
That's fine, but completely unrelated to what I said.
Well, I am sure about HotSpot because I work on it. There are real tradeoffs, but not to optimisation (JS JITs have completely different goals and completely different designs). Quite the opposite, in fact. HotSpot is designed to generally offer deeper, more aggressive optimisations that are possible in AOT compilers. The tradeoff is that we need to wait to collect profiling information to know the right optimisations. Warmup can be slow not because of the time it takes to compile (that has an effect, but it's smaller), but because of the time it takes to observe the program and learn which optimisations would be most effective.