19

I have always wondered, why does Java require you set the heap size manually? I was under the impression that programs written in other languages would just allocate as much memory as needed as the program run until the OS could allocate no more.

In the Java world we need to set the heap, stack, and permgen size. While this is simple enough forgetting to increase these to "large enough" numbers is the #1 reason I have seen servers go down.

Why is it not possible to tell Java to grow the heap/stack/permgen as much as it needs over time?

benstpierre
  • 32,833
  • 51
  • 177
  • 288

5 Answers5

7

Three reasons:

  1. Because Java was intended to be a language for writing web apps. It is generally not thought to be a good idea to let a web app take over all of the machine resources.
  2. Because Java is garbage collected. As well as specifying an upper limit of memory, the heap size triggers garbage collection too. Essentially you are saying "you can use this much, but when you hit that limit you've got to tidy up".
  3. There are many classes of applications where you do want to limit the amount of memory used by the Java process, e.g. where it is more important that other processes continue when there is insufficient memory for both.
  4. Because being able to limit heap size is a feature. If you like the approach where the process can have unlimited memory, (as on the other languages mentioned) then you can always set the heap limit to be more than it could possibly acquire. If you want to limit heap size, you can do that. Other languages have only one of those possible behaviours, making them less flexible.
DJClayworth
  • 26,349
  • 9
  • 53
  • 79
  • 2
    Do you have a source for the first point? I've never heard the "java was intended for writing web apps" thing before (not that I've gone delving into java's history, either...) – Mike Aug 18 '10 at 22:14
  • 4
    Holy mis-moderation. Java was descended from Oak which was meant to implement set-top box software, like the kind you might have had in sophisticated cable TV tuners. And as far as the garbage collection goes, garbage is collected when object are inaccessible, not when the memory limits are reached. – Edwin Buck Aug 18 '10 at 22:25
  • @Edwin Buck: `garbage is collected when object are inaccessible, not when the memory limits are reached` True, but they are not "immediately" GCd. How fast you have to DOES depend on heap size and can be extremely important for performance. – Enno Shioji Aug 18 '10 at 22:35
  • From the periodicity of the tons of gc graphs obtained through jconsole, I can assure you that garbage collection runs concurrently releasing objects in small batches as if on a timer basis, and doesn't run on a "how close are we to the limit" basis. The only exceptions might be if you're about to exceed the limit, then garbage collection will get one "last chance" to discard objects before the JVM throws in the towel with an OutOfMemoryException. – Edwin Buck Aug 18 '10 at 22:49
  • you also find visualization within the same JVM noawadys with stuff like Waratek – Nikos Oct 12 '13 at 12:51
  • @EdwinBuck The JVM does look at "how close are we to the limit" to determine when to start GC. For example you can use the `-XX:CMSInitiatingOccupancyFraction` flag for setting that limit for CMS. See [useful JVM flags](https://blog.codecentric.de/en/2013/10/useful-jvm-flags-part-7-cms-collector/) for more info. – stephenbez Nov 09 '18 at 05:46
  • @stephenbez Of course that blog was written 3 years after this question was answered, but the flag was there in 09. Again, that doesn't mean that the Concurrent Mark and Sweep garbage collector was in place for any particular JVM (gc was replaceable even then). Even then, the spec still stated GC would reap unreachable objects, not GC would fire up when memory limits were exceeded (although there are emergency GC sweeps when the heap runs out of space). – Edwin Buck Nov 09 '18 at 23:16
6

My interpretation is that Sun is a company focused on selling Big Boxes and they like that the sysadmins can do things on these boxes. Running a system to fill all the memory is a good way to run it into the ground and be unable to efficiently take action to restore operation because you cannot allocate memory to create a login shell for example.

Peter Tillemans
  • 34,983
  • 11
  • 83
  • 114
4

I think because actual memory of computer is finite. So, in a sense, JVM allows you to detect memleaks before all memory is wasted.
Plus, what to do if you run several JVMs on the same machine -- in this case how do you allow each of these JVM to grow "as much as it needs"?

Victor Sorokin
  • 11,878
  • 2
  • 35
  • 51
1

Because growing the heap, stack, and permgen size dynamically just would make the server go down anyway. In such a world, the server would eventually leak away all of its resources.

Also, developing automatic memory management wasn't as mature as it is today. Having virtual limits makes things easier if you pick the wrong defaults, but it can make the coding a bit less efficient on the back end.

Yes, these are guesses, but reasonable ones; especially when you consider Java's / Oak's origins of embedded set top box programming. It isn't like an embedded system is going to have swap or disk backed virtual memory, so why make the JVM act as if it were available?

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
0

Old topic but I got here and I think I know the answer.

Complementing what Peter said, the Java ecosystem is entirely designed for system administrators and support teams. In the same way that the administrator defines the memory resources that he wants to be used by the application, the same happens with database connections (JNDI) in which you do not need to give the application or your developer where the database production is, just the name that references the resource. Everything Sun did had a perfect mission-critical management system. In the case of the Solaris operating system, Sun has developed a feature called "projects" (https://docs.oracle.com/cd/E37838_01/html/E61042/index.html) that serves for the administrator to limit server resources in applications of any programming language (as you mentioned above). Therefore, it is important for a production system to let the system administrator know how much resources the application is able to use and to be able to limit what is necessary. And this is not unique to Java or Sun products. In the case of .NET it is possible to limit these resources (https://learn.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/processmodel), Ruby (https://gist.github. com/jjb/7389552), Node.JS (How do I determine the correct "max-old-space-size" for node.js?) and etc.

Learning to manage is important like learning to develop. A lot of people think Docker is a modern marvel while FreeBSD Jails, Solaris Zones and so on existed a long time ago. What makes good software not fail is that it is well written and well managed.