Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Can anyone explain to me why JVMs (I didn't check too many, but I've never seen one that didn't do it that way) need to run on a fixed heap size? I know it's easier to implement on a simple contiguous heap, but the Sun JVM is now over a decade old, so I'd expect them to have had time to improve this.

Needing to define the maximum memory size of your program at startup time seems such a 1960s thing to do, and then there are the bad interactions with OS virtual memory management (GC retrieving swapped out data, inability to determine how much memory the Java process is really using from the OS side, huge amounts of VM space wasted (I know, you don't care on your fancy 48bit machines...)). I also guess that the various sad attempts to build small operating systems inside the JVM (EE application servers, OSGi) are at least partially to blame on this circumstance, because running multiple Java processes on a system invariably leads to wasted resources because you have to give each of them the memory it might have to use at peak.

Surprisingly, Google didn't yield the storms of outrage over this that I would expect, but they may just have been buried under the millions of people finding out about fixed heap size and just accepting it for a fact.

share|improve this question
    
The design of EE application servers would make perfect sense even without this "circumstance" as the JVM itself needs some space, and switching between threads is cheaper than switching between processes - that's one of the things that made Java big in the late 90s. –  Michael Borgwardt Dec 6 '12 at 13:29
    
This is kind've a rant, and I wonder how much thought you've put into it. For example, how would the GC/swap interaction change if you didn't have a heap limit? How is VM space wasted? You get your 2/3Gb space whether you use it or not, and if you're pushing the limits of that space it doesn't matter whether you've got a fixed or floating heap. For that matter, how do multiple JVMs waste anything other than swap (which should be configured appropriately for the machine's purpose)? –  kdgregory Dec 7 '12 at 12:11
2  
It is kind of a rant, but it is informed by years of daily experience writing and operating a Java based platform. If you don't do swap (because it will make your system unresponsive for 20 minutes until the the runaway process runs out of space to allocate) and have memory overcommit turned off for stability reasons (the OOM killer is not very good at picking victims), you care about VM space, and contrary to what people below are implying, launching a Java VM with -Xmx2048m will immediately allocate 2GB of virtual memory (at least in my Sun JVM on Linux) for an program with one variable. –  themel Dec 7 '12 at 17:56
    
Excellent question. Been wondering the same thing. But which of the "facts" presented here in q and the answers are correct? –  Martin Ba Dec 9 '12 at 6:25
    
For the reactions you were looking for, simply mosey along to the sun bug tracker... eg here, here and here. Read those and feel the indignant rage :) –  Basic May 30 '13 at 21:44
add comment

4 Answers

You are wrong. The heap size of JVMs is not fixed, only bounded:

  • -Xmx sets the maximum heap memory size
  • -Xms sets the minimum heap memory size

Setting an upper limit is necessary for several reasons. First, it tells the garbage collector when to spring into action. Second, it prevents the JVM from clogging the whole machine by consuming too much memory. The minimum heap size is probably useful to reserve the ammount of memory the program needs at least, to prevent it running out of memory (because other processes consume too much).

share|improve this answer
9  
no the min is the default to avoid a slow startup when a lot needs to allocate resulting in repeated heap increases, paging will deal with the physical ram running out –  ratchet freak Dec 6 '12 at 12:52
    
@ratchetfreak that was my second guess ;-) –  user281377 Dec 6 '12 at 14:14
    
@user281377 If this is the case, then how can C# run just fine without a maximum heap memory size? –  cmorse Nov 5 '13 at 18:13
    
cmorse: I can only guess. Maybe Java is targeted at large servers, where many applications share resources and strictly enforced limits are desirable, while .net is rather made for PCs and smaller, more dedicated servers. –  user281377 Nov 6 '13 at 13:05
    
@user281377: The Java applications I have used that run out of heap space generally handle it very poorly, generally just crashing or being very flakey thereafter. And ASP.net runs on both large and small servers just fine. What I really don't get is why by default, Java enforces this limit. I would love to hear from the reasoning behind their decision...I'm sure they had a good reason. –  cmorse Nov 7 '13 at 22:23
add comment

As says user281377, you only specify an upper limit of how much memory your process can consume. Of course, the application itself will only grab the space it needs.

Whether there should exist a default upper limit or not is another question, with both pro and contra.

share|improve this answer
add comment

I imagine the answer has something to do with Java's heritage. It was originally designed as a language to be used for embedded systems, where obviously resources are constrained and you don't want processes to simply gobble up whatever's available. It also helps with system administration, as it makes it easier to provision resources on a server if you can set resource limits. I see that the latest JVMs seem to use multiple non-continuous heaps, although of course it all appears as a single heap to your code.

(FWIW, you had to specify a program's memory requirements under Apple's pre-Darwin MacOS versions [up to System 7 anyway, which was the last one I used], which was well into the 80s.)

share|improve this answer
1  
+1 - for being (1) the only answer that actually addressed the question, and (2) being plausible. –  kdgregory Dec 7 '12 at 12:06
add comment

You need to give the GC some mechanism to tell it when to run, or your program will fill up the entire virtual memory space. There are many alternative ways to trigger GC: elapsed time, number of allocations, number of assignments, probably others that I can't think of right now. IMO none of those are as good as simply setting a memory boundary, and running GC when the allocated space hits that boundary.

The key is to set the correct boundaries. I look at -ms as "this is how much memory my app needs," and -mx as "it should never exceed this amount." In a production deployment, the two should be close if not equal, and they should be based on actual, measured requirements.

Your concerns about "wasted" virtual memory are misplaced: it's virtual, it's (almost) free. Yes, giving the heap too big an allotment means that you can't start as many threads, or load as many memory-mapped files. But that's part of application design: you have scarce resources, you need to partition them in a way that allows your application to run. In a "C-style" heap, which will expand until you hit the top of memory, the basic issue is the same, you just don't have to think about it until you're in trouble.

The only thing that a large heap might "waste" is swap space, because all writable segments require a commitment from swap. But that is part of system design: if you want to have lots of JVMs running on the same box, either increase your swap or decrease their heap allotment. If they start thrashing, then you're trying to do too much with the system; buy more memory (and if you're still running a 32-bit processor, buy a new box).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.