from Hacker News

The JVM is not that heavy

by khy on 2/1/17, 6:08 PM with 367 comments

  • by gregschlom on 2/1/17, 7:33 PM

    Also worth noting that the JVM itself only weighs a couple of megabytes. The bulk of the size comes from the Java runtime (ie: the "standard libraries"), and there are lots of things that your app may not need there (XML parsing, serialization, etc...)

    A couple of years ago I wrote a simple tool (https://github.com/aerofs/openjdk-trim) that allows you to filter out what you don't need. We were able to get the size of OpenJDK from 100MB down to around 10MB.

    Note that the work of determining which classes you need is entirely manual. In our case I used strace to check what classes where being loaded.

  • by martingxx on 2/1/17, 8:06 PM

    I led our teams to switch from Java to Go because of the productivity of development, but then noticed deployment was simpler and faster, memory usage was slashed (for comparable applications), request/response times were much more consistent, startup was practically instant and as a result we started aggressively rewriting Java applications to Go and saw a notable difference in the number of machines we needed to run in AWS.

    So in my situation, the JVM is heavier by every single measure listed, and for each by a considerable margin.

  • by nikcub on 2/2/17, 9:10 AM

    Microsoft seem to have learned a lot from Java in designing their new .NET Core CLR. It has gotten almost everything right:

    * a small and fast CLR (JVM)

    * a class library that defaults to almost nothing but primitive classes

    * proper and standardized version, platform and package management (NuGet)

    * open source and MIT license[0]

    * a patent promise[1]

    * arguably the best dev IDE available (Visual Studio) and one of the best up-and-coming dev text editors (VS Code)

    * Native ORM, templating, MVC, web server so there is one way to do things

    * open source middleware standard (OWIN)

    * they left out, for now, attempting the hard ugly stuff like x-platform GUI

    * all platforms are equal citizens, they acquired Xamarin for dev tools and release their own Docker containers.

    * it's already getting good distribution (on RedHat) even tho it's only 6 months out from a 1.0 release.

    Java may have missed the window for fixing some of these issues in their platform - I feel that if Android were being developed today, they'd almost certainly take .NET Core as the runtime.

    I've yet to commit to using .NET Core anywhere, but from what I know about it so far it is impressive.

    [0] https://github.com/dotnet/coreclr

    [1] https://raw.githubusercontent.com/dotnet/coreclr/master/PATE...

  • by jhh on 2/1/17, 7:17 PM

    I agree with many points in this article. That being said, there are dimensions of heaviness not captured in the article as far as I can see:

    1. The startup times, not so much of the JVM itself, that just takes 1,5 secs, but the startup time of your application gets higher if you have a lot of classes on the classpath. I guess it's the classpath scanning that takes a lot of time (?).

    2. Memory usage of Java objects is quite heavy. See this article: http://www.ibm.com/developerworks/library/j-codetoheap/index...

    3. The heavyness of the ecosystem in terms of the magnitude of concepts and tools being used and the enterprisy-ness of libraries.

  • by linkmotif on 2/1/17, 7:26 PM

    This interview with Bob Lee is really interesting on this topic: https://www.infoq.com/interviews/lee-java-di.

    Apparently, Square was first built out on Ruby with the mindset that the JVM is an old clunker.

    Fast-forward a few years they switched to the JVM because it was faster and the language (I know, not related) provided compile-time safety.

  • by Jeaye on 2/1/17, 11:34 PM

    Java, especially JAR files, can be quite light weight. However, JVM environments, and development with Java and Clojure, can be very heavy _and_ slow.

    For Clojure, starting `lein repl`, takes 16 seconds on my 2012 Macbook and 9 seconds on my similarly-aged Dell laptop, both with SSDs and i7 quads.

    Regarding memory usage examples, the base memory usage of a Google App Engine instance running the move trivial Hello World Java program takes around 140MB. Given that the default F1 instance has a soft memory limit of 128MB, it becomes clear that the JVM is working against you in both cost effectiveness (the price to spin up new instances as your existing ones are already above the soft limit) and latency (since spinning up instances is slow). Add Clojure on top and the problem certainly doesn't get any better. As an added annoyance, which is specific to App Engine but a result of using the JVM, it's impossible to specify JAVA_OPTS, so any of the -X flags, without switching to the Flexible environment.

    As a result of both of the above, choosing Clojure for developing on App Engine, as my specific example, has had the serious downfall of slow development tools and memory issues out of the gate on my instances, causing me to pay more for a beefier instance class. The REPL is really hard to beat, but the combination of JVM and Clojure are the biggest pain in the ass, with this stack.

  • by saosebastiao on 2/1/17, 7:17 PM

    Interesting that all the comparisons were with server frameworks. As if anybody ever cared about a few hundred megabytes of overhead on a server. Hell, even a bloated JVM implementation fits in most server L3 caches.

    On the desktop, laptop, phone, or embedded environment, the JVM is heavy. It starts up slow, jars carry around ridiculous amounts of dead dependencies, garbage collectors require immense amounts of tuning, etc. And we shouldn't really expect otherwise. If you can't even keep your VM in cache, how are you supposed to have fast application code?

    Specialty closed source JVM vendors have done wonders in terms of improving this problem...but it's still an uphill battle. AOT native compilation down to machine code is becoming more popular because of the proliferation of resource-constrained environments, and it will take time for new languages/compilers to take over, but take over they will.

  • by cperciva on 2/1/17, 8:02 PM

    The notion that the JVM is not heavy because it needs less than a GB of disk space seems crazy to me. I consider OpenSSL to be wildly bloated because it is over 1 MB.
  • by sunkencity on 2/1/17, 8:09 PM

    Sure it takes a while to load and there's bloat, but the bloat is everywhere now.

    On the bad site of the JVM and assorted Java tools is that they are second class citizens of the unix world. The command arguments are all messed up, much like a windows tool ported to unix, and the interaction with the rest of the unix stack like sockets, files are all solipsistic and off, which leaves an ill stink on everything touched by it.

    One of the things I find funny with java is the once upon a time much touted security model, fast forward a couple of years and the event of android - using the unix security model and none of the java stuff.

  • by nightcracker on 2/1/17, 9:01 PM

    OP is impressed by running 5 processes at once while claiming that the JVM is not that heavy.

    Is this cognitive dissonance? Dishonesty? I don't understand.

  • by hardwaresofton on 2/2/17, 4:29 AM

    I was a little surprised that he author disliked "heavy" things, yet kept reaching for the absolute heaviest tools in their respective categories:

    - Rails (just about the heaviest web framework ever made for ruby, despite it's wide appeal)

    - Ember (I absolutely love ember, but it is by far the heaviest modern JS framework... I don't include things like ExtJS)

    Also, I routinely use the heavy/light distinction, but it seems in a completely different way. I almost don't care how heavy something that run on the server-side of a web application is, on the back-end "heavy" generally translates to "contains complexity I'm not willing to deal with". "heavy" on the frontend for me means both in footprint and complexity.

  • by vvanders on 2/1/17, 7:08 PM

    Start-up times are still an issue with Clojure on the JVM. For instance with Android I've found the initialization times to be pretty much a show-stopper for any application development.
  • by relics443 on 2/1/17, 7:08 PM

    I've been using these arguments at my company for years. There's definitely FUD surrounding the JVM, and it's pretty ridiculous. Sure, it's not a perfect system, but it's usually disregarded for being "old and bloated".
  • by Perseids on 2/1/17, 11:54 PM

    > I run at least 5 JVM processes on my 2012 MacBook Pro with 8GB of memory. This is all day, every day. I would never have tried to start 5 Rails apps at the same time.

    Where have we gone wrong that starting 5 processes with 8GB RAM seems impressive? On my development PC I regularly run: - two different browsers (Firefox and Chrome), - an Email Client that is a slimmed down browser suite (Thunderbird), - two chat apps and an IDE that are browsers in disguise (Electron and Chrome App). And that is without me running and testing any of the applications that I'm actually developing. Oh, and then automatic testing starts yet another browser. Even better, my actual application runtime environment then runs in its own full OS virtualization, because otherwise the deployment environment differs from my development environment… If we can't slim down the runtime environments of our day to day apps and development tools, how are we going to survive the end of moore's law with the ongoing trend to hide everything behind more and more abstraction and virtualization?

    And I disagree with many others here, that RAM usage just doesn't matter for server development. At my last project, our setup contained a few macro services and the ELK stack for logging which accumulated to five JVMs and three Node instances. Now this is ok for the live setup, because most of these will run on different machines anyway. But for testing you want to have them all on the same machine, for convenience on the Jenkins machine. And you want separate setups for integration tests, user acceptance tests, and demo purposes. All of these have basically no load, but still consume the full amount of RAM. Of course, you will say, just get more machines, we are in the age of the cloud! But that doesn't come for free: Now every Jenkins job needs different credentials to access the machines, all developers need access to every machine, every new setup needs an additional cloud provisioning step, possibly with approval from management because of the additional fees. And yeah, you can automate most that away, but building and maintaining that automation also carries its own burden. All of that for something that should be essentially free – it's not like my OS doesn't already run a few hundred processes when I have just started my window manager.

  • by rb808 on 2/1/17, 7:28 PM

    Not just heavy but I really don't like all our processes named "java" with stupid -D cmd line parameters. A Nice native binary app will let you can name it what you want with config as you like it.
  • by CaptSpify on 2/1/17, 8:59 PM

    I feel like I'm missing something. His argument seems to be "the JVM isn't heavy compared to other large and bloated systems". Well... sure. My car isn't heavy when compared to a tank, but if I want light, I'll use my bike.
  • by jmspring on 2/2/17, 3:33 AM

    I've never had a problem with Java the language being heavy. However, many code bases due to annotations, dependency injection, etc. from a development perspective really aren't any longer Java. You need to understand the code base, the app itself, etc.

    This happens with open source projects as well. I contributed to the Azure support for JClouds and the bulk of my ramp up time was understanding how things were done more than writing the code itself.

  • by ysleepy on 2/2/17, 12:03 AM

    Java does not give memory back to the system very quickly per default. This blows up the memory allocated to the jvm considerably.

    start it with:

       java -XX:+UseG1GC -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15 -jar ...
    
    and the jvm will give back to the system. see http://imgur.com/a/m9Qxx
  • by bsaul on 2/1/17, 7:50 PM

    i think most people wouldn't say the jvm is heavy compared to ruby or python runtimes, but rather golang , rust or swift. Aka : 1 file copy deployment, almost no boot time and 0 memory bloat.

    the first time i ran a server in go and realized it took a few kilobytes in ram when nothing happened, i was quite in shock.

  • by vmarovic on 2/1/17, 8:17 PM

    "For both Node and Ruby you need a C compiler on the system which is hundreds of megabytes alone." Wait what? What c compiler is hundreds of megabytes?
  • by it on 2/1/17, 10:32 PM

    I keep seeing plenty of evidence that the JVM is indeed heavy. When I was working at a startup and we were running Solr on the JVM, it kept running out of memory and crashing. When I tried using Clojure I was irritated by the startup time of the REPL on the JVM. More evidence: http://stackoverflow.com/questions/13692206/high-java-memory....

    If you want something light like Clojure and don't need any Java libs, try Pixie. https://github.com/pixie-lang/pixie

    If you want something light not like Clojure, Go is a great choice. It's fast to compile, fast to run and doesn't gobble up your memory unless you force it to.

  • by geodel on 2/1/17, 7:55 PM

    So JVM is not heavy compared to even heavier stuff. However compared to Go it is quite heavy in term of disk, RAM usage, and deployment.
  • by outworlder on 2/1/17, 7:23 PM

    Interestingly, the author does not touch startup times.

    Frankly, for server-side loads, no-one cares how much your runtime weights, be it disk space, download size and even memory (heck, my last project required developer workstations with at least 96GB).

    There are all sorts of environments where that matters. And that's one of the reasons why Clojure didn't catch on on Android.

  • by tlrobinson on 2/1/17, 8:25 PM

    Well, I sure wish I knew how to make our Clojure dev server (`lein ring server`) take less than 2 minutes to start up on a 4 core i7 16GB MacBook Pro.

    Fortunately I typically only need to restart it when switching branches.

  • by hannob on 2/1/17, 9:36 PM

    I must admit my experience is a few years old, but one thing that the whole text doesn't mention and that has contributed a lot to the negativity I feel towards the java ecosystem: It seemed not well integrated in the Linux ecosystem.

    What do I mean? I often experienced that Java dependencies were not readily available in Linux distros. Packaging Java stuff was - weird and complicated, not sure how to better phrase it.

    For Python/Ruby/PHP you usually can rely on the fact that major libraries are properly packaged. For Java not so much.

  • by sandGorgon on 2/1/17, 7:12 PM

    I used to think this too, until I came across http://www.scylladb.com/

    It is a fork of cassandra written in the Seastar c++ framework and is drop-in compatible with cassandra. Claims 10x increase in performance.

    I always thought there was a few percentage points difference - never a 10x performance difference between java and c++. And that too for a project with as many man hours and facebook-scale tuning as cassandra.

  • by DrBazza on 2/1/17, 8:01 PM

    We run an algo trading system using 10-20 JVMs depending on exchange. It's not so bad.
  • by mi100hael on 2/1/17, 9:37 PM

    If you're installing a compiler on your production server, you're doing it wrong.
  • by w8rbt on 2/2/17, 12:17 AM

    Jars are just awesome for cross-platform work or for when you need easy deployment. I oscillate between Java and Go now for similar tasks. They are both great for cross-platform and easy deploys/frequent updates. Go is better at systems stuff (that's expected as it is the new C IMO). Java is better if you want a boat-load of rich data structures at your finger tips (more than slices, structs and maps... Go feels bear bones here, but I like it that way just as I like C that way). They both perform about as well as C and C++ for most things and are safe and fun to use. I like C and C++ too, but I'm getting too old to use them.
  • by liveoneggs on 2/2/17, 1:34 AM

    The reputation of "heavy" was hard-earned back in the bad-old-days (1.3 era) when EVERYTHING NEEDED to be written in java and the JVM still sucked.

    I, literally, had a party at work when we got our web app to three days of continuous uptime without an OOM error; nevermind that the early JIT (1.4 era) took 12+ hours to get "warmed up" and give peak performance.

    Don't misunderstand me- java's horribleness has given me a pretty nice career so, for that, I love it. For the years and years of broken promises- (OSGi without running out of PermGen? lol) I hate it.

    Java is not lightweight by any means; computers are just faster and have more memory.

  • by alsadi on 2/1/17, 8:40 PM

    Ruby is perl-minded folks reinventing python without understanding it. The result was: ruby is python-done wrong.

    Now comparing python flask uwsgi and jvm jetty apps are in favor of python in all metric.

    Starting a django elephant takes no time compare that to starting less capable framework of choice in java world.

    To be fair, java can be much much faster than python. But usually you don't care because python is not the bottleneck. Ex. The bottleneck can be in the SQL query

  • by Jach on 2/2/17, 1:12 AM

    Work on an enterprise-sized "app", the JVM starts seeming "heavy". It feels super slow (and memory greedy, and you have to make sure it has enough of the right 'type' of memory) in executing on a whole (when it gets going it can do limited, specific things quite fast) and for productivity, as does all the tooling around it. Unless perhaps you're Google and you have server farms constantly compiling crap and so on so devs don't have to notice as much. Most of the negative feelings are probably the fault of having a ginormous app in the first place, I'd likely feel similarly about C++. Still, even when it's just a somewhat-large app (like a database, or an IDE) I've felt it in Java whereas working on a similarly large app in other languages doesn't have the same feeling. I've never really felt it when just writing a REST/SOAP API that's effectively a thin wrapper around some DB calls. Like a blog could be, but there are many other similarly small things. But those sorts of small problems can be done effectively in most any language, and 'heaviness' is probably very low on one's priority list...

    I think there's an incentive with more dynamic languages to decompose your software into smaller bits. When the language gives you the ability to "script" that helps even more. You don't need to bundle everything into an uberjar, you can run things independently, and therefore you don't even need all of the sources locally, just what you need to do your particular bit of data processing. It's possible to do this with Java and multiple JVMs, but it's hard, the incentives aren't there. Unfortunately I don't have experience with Clojure in the large to say whether it helps make the JVM feel lighter, from my side projects it seems like it could but I don't know if the community is going that way. Lispy languages have different incentives since they let you build from the bottom up so well.

  • by david-given on 2/1/17, 7:09 PM

    Way back when I ran a comment engine that was a custom Java servlet running on an embedded (i.e. mostly interpreted) JVM on a NSLU2: a 266MHz ARM with 32MB RAM. The servlet container was Winstone. Can't remember what the JVM was, sorry.

    Load wasn't exactly high, but it worked absolutely fine.

  • by jwr on 2/1/17, 11:41 PM

    What most people seem to miss is that if you use Clojure, the startup time hardly matters, because you do not restart your development JVM often.

    I find this similar to discussions about boot time. It doesn't matter -- I reboot my computer once a month, if even that.

  • by my123 on 2/1/17, 7:01 PM

    Note that you can also use IKVM and then Mono AOT if you don't want a JIT at all.
  • by eikenberry on 2/1/17, 9:57 PM

    I see no mention of the additional cognitive load a complex runtime adds. This to me is the 'heaviest' part of the JVM. Though I admit it is not necessarily the same class of things the author is discussing.
  • by PaulHoule on 2/1/17, 8:54 PM

    Clojure is heavy, or at least it has high start times. Some of that is the JVM start, but parsing and compiling a large amount of Clojure code system-wide is more of a burden than, say, CPython.
  • by ericfrederich on 2/2/17, 2:16 AM

    You know it's not heavy because there are blog posts about it being not heavy. I also know Python's GIL isn't a problem because there are numerous posts about it not being a problem
  • by justinsaccount on 2/1/17, 7:42 PM

    It's not the JVM, it's the tooling.
  • by nhumrich on 2/2/17, 2:31 AM

    If you don't think the JVM is heavy try running it on a t2.micro. It can never get enough memory to start. I haven't ran in to any other language runtime that won't run on a t2.micro
  • by ohstopitu on 2/1/17, 8:47 PM

    Just out of curiosity: If you decide to use Java (or any other languages that run on JVM), are their 3rd party libraries as "nice" (read: as many) as npm?
  • by stevefeinstein on 2/2/17, 1:28 AM

    That cough medicine doesn't taste that bad. If you have to use "that". It's the thing.
  • by rahilb on 2/2/17, 1:24 PM

    I wish I was as good as the developers commenting how slow java is to start. They are clearly on a higher plane of enlightenment where 1.5 seconds to start ruins their day, their deployment process, and development cycle.

    More power to them.

  • by doggydogs94 on 2/1/17, 10:37 PM

    The biggest problem with Java is not the JVM, but versioning. Many Java applications encounter difficulties when the wrong version of Java exists on a computer. This leads to many siloed computers to maintain.
  • by sjg007 on 2/2/17, 12:44 AM

    And it is better than a segfault.
  • by djsumdog on 2/1/17, 11:05 PM

    A lot of Java apps are shit at packaging too. They often include an entire Tomcat server with all the setup files you don't even need. I wrote this a while ago:

    http://penguindreams.org/tutorial/embed-tomcat-in-your-appli...

    ..but don't do that. Instead use something newer like netty and ditch that decades old crappy servlet layer you don't need.

    You can also use sbt+onejar or sbt-native-package to make either a single jar runnable or a standard deb/rpm/tar.gz package to run your service.

  • by djsumdog on 2/1/17, 10:59 PM

    What the hell is an HCMB? Nothing on DuckDuckGo, and nothing on Urban dictionary. I wish people would stop using acronyms before defining them.
  • by vacri on 2/2/17, 6:29 AM

    > I, for one, am relieved not to have run apt-get install build-essentials on a production box.

    Well, whoever does this is Doing It Wrong.

  • by debacle on 2/2/17, 1:03 AM

    JV-what? I just installed nuget on ubuntu and what is this?