JVM is fine if you're running only a single instance of it: just use threads instead of processes. The problem with JVM is that you often can't afford to have several of them running: in Java world everything is measured in hundreds of megabytes, that's the smallest unit of measurement they use (often supplemented with references to 32GB servers, "they're so cheap now"). Check out Batik Java library for rendering SVG. A single 45Kb SVG file, when fully parsed, eats up 150MB right here on my laptop. After serveral repeated test runs, JVM memory usage grew to a sweet 540MB, where it stopped because I capped it there via -Xmx. For comparison: Inkscape, which is an entire SVG IDE powerhouse, not just a parser, consumes only 3MB more when I open the same file in it, so that's like 50x less, plus it doesn't grow.
See, unlike CLR or Python/Perl/Ruby, JVM truly is a virtual computer, i.e. running a WAR file under Tomcat is kind of like running an Office 2008 inside of an invisible VMWare image with Windows pre-configured to occupy either 500MB or 1GB or comparable number. I just don't get why Java people are so damn proud of it. Moreover, they find nothing strange about this bizarre arrangement because they're completely absorbed by that JVM instance.
To demonstrate why Java doesn't belong on UNIX I invite you to implement find, grep, less and sort as Java programs, pipe them all together in a bash console and enjoy the show. :-)
In the end, there is nothing with Java that can't be dealt with by paying a few extra $ for hosting. The main issue is that JVM is an OS, a much more corporate, boring, uptight and over-engineered (and much less fun) than UNIX is.
I also want to address some of Tobias42 comments: for the most part I absolutely agree with him, except I don't follow his comparisons to Rails: we are comparing platforms here, not languages or frameworks. JVM is a memory hog compared to UNIX, and if he wants to compare Rails, I'd recommend loading his Rails app into JVM via JRuby/Tomcat and seeing what happens to his 192MB VPS box. Moreover, I wouldn't call 100ms/page (i.e. just 10 requests/second) "lightning fast", which makes his next comment about "Rails taking 10x longer" sound a bit strange: how hard does one need to try to build a web application with 1 request/second performance?
A Java web application however needs very little additional memory per request-handling thread, which makes its memory footprint much smaller when many parallel requests are involved.
100 ms for the home page in my Java app might not be great but, considering that 7 separate queries to the database are involved and that it runs on a very weak server, I think it is quite decent. And because of the use of concurrency (threading) there is a good chance that 100 ms for a single request translates into more than 10 requests per second. But I still wouldn't call my webapp lightning fast. I was calling java lighning fast because in my case I still get decent response times on bad hardware and with an inefficiently programmed application (7 db requests that could as well be cached and only refreshed every hour or so).
You are absolutely right about the rails app however. The 1 second response time is not normal. I just measured again and suddenly I get similar response times as for the java app. The server must have been under heavy load before (maybe the automatic backup). I admit that my quick measurements are not very representative and apparently not reproducible reliably, but still: about the same response time as the Tomcat with no database activity and on a faster server. I also checked a different rails project of mine running on an equivalent VPS. Pages where two simple database request are involved, which, when directly invoked in psql, take 15 ms, take 300-400 ms to load if not cached.
If a page takes 100ms, that doesn't mean you only have 10 requests/second. With a little care you can have thousands of requests per second, especially on top the JVM.
> A single 45Kb SVG file, when fully parsed, eats up 150MB right here on my laptop.
That's not the fault of the JVM, although I do agree that many Java-libraries are memory-hogs.
The only difference between the JVM and CLR/Python/Perl/Ruby is that the JVM doesn't return the used memory to the OS. This means that if the JVM reaches 1 GB of used memory, it will remain there even if the GC kicks. Also, when allocating memory, the JVM has to allocate more memory than it needs because it needs space to degragment the heap. But on the other hand compared to CPython / Ruby MRI / Perl ... the JVM's GC is generational and heap-compacting, making it much more efficient memory-wise for long-running processes ... allocation is cheaper, deallocation is smarter and you won't end-up with a heap that looks like swiss cheese.
But the point is: If you add additional stuff, the larger part of the memory footprint of that additional stuff is only added once, because you don't need a new Tomcat for every request which you process in parallel, but only a very lightweight thread.
(Where "loaded up" equals a lot more than Rails/Django/etc gives you out of the box. We have a separate Tomcat running with a Solr instance for search, but that's for deployment reasons. If we put that in the same Tomcat I might push the RAM up to 192M, but it would probably be fine as it is)