
Java 12 - kalimatas
https://jdk.java.net/12/
======
MarkMc
I'm so glad I was taught Java at Macquarie University back in 1998. For the
past 20 years I've had a career built on a solid API that doesn't change every
2 years like some flavour-of-the-month Javascript framework.

Even on the client where Java has lost to Javascript, I'm finding it more
enjoyable to add features to my 15-year-old SWT app [0] rather than dealing
with the multiple layers of abstractions that is Javascript+CSS+DOM (+ maybe
Electron). Personally I think it's a shame Sun dropped the ball with client
Java - if they had chosen SWT over Swing and provided a minimal JVM then maybe
Java Web Start would have beaten Javascript web apps. It's also a shame Sun
sold Java to Oracle - Google would have been a better steward, and probably
would have been willing to pay more for the Java parts of Sun.

I'm now trying Dart to develop a few Flutter apps. It's no doubt a better
language, but not _that much_ better - I think Flutter would have been more
successful if it was built on Java.

[0] [https://www.solaraccounts.co.uk](https://www.solaraccounts.co.uk)

~~~
tannhaeuser
The times of ever-changing JavaScript frontend frameworks is long behind us
(and, arguably, React has won for MVw-style browser apps). The core node.js
web serving APIs (expressjs and core http request API, which expressjs
middlewares forwards and decorates) is stable since node.js v0.1 or at least
2015, and infinitely better than Java's servlet, JSP, and taglib APIs
(web.xml/jetty-config.xml anyone?).

The flip side of Java's stability is stagnation. On the server-side, customers
use mostly Spring/Spring Boot these days to make Java's overengineered stack
usable, using even more over-engineering and metaprogramming. Same with
maven/gradle, which turns what should be a developer-focussed build system
into an enterprise XML mess.

SWT? I'm glad it works for you. Last I heard, IBM had pulled out of developing
Eclipse and SWT/RCP over ten years ago. In the one project where we used it,
the app looked like an IDE, and customers hated, then cancelled it. Designed
as wrappers for OS-native GUI controls, it has even less of a place in a
browser than Swing had. Last I looked, of the Java rich-client frameworks,
only Swing has been updated with HIDPI support, whereas JavaFX and SWT
haven't. None is using any of those (with the exception of experimental JFX
apps) for new apps in this decade.

~~~
lmm
> On the server-side, customers use mostly Spring/Spring Boot these days to
> make Java's overengineered stack usable, using even more over-engineering
> and metaprogramming.

There was definitely an era of that, but over the past decade or so it's been
acknowledged as a problem, and there's been a lot of effort put into making
things simpler and more vanilla. Modern Spring is much much closer to plain
old code. (Of course it's still possible to write in the XML/setter
injection/afterPropertiesSet style, and always will be - that's backward
compatibility for you - but it's very possible to migrate existing
applications to a better style in place, which very few platforms manage).

> Same with maven/gradle, which turns what should be a developer-focussed
> build system into an enterprise XML mess.

Maven is pretty close to the perfect build system, it's just taken a while for
knowledge and practices to catch up with it. All the stuff people love and
praise Cargo for, Maven has been doing for 15+ years.

~~~
tannhaeuser
The basics of maven might be sound (though it could make it easier to work
with local dependencies) and npm et al have basically copied it. Where maven
dropped the ball is the myriad of maven plugin magic, maven's implicit
lifecyle, and a pom.xml's Turing pits, etc. I've developed Java apps since
almost the beginning, and am as much of a markup geek as could be, but still
hate maven with a passion, and often times do not understand what tf it wants
from me. I just don't have the patience with wading through crap that 2003ish
Java nerds thought would be a good idea. And increasingly, as Java libs get
EOLd, this will be a major problem for monolithic Java apps with tens of
submodules. I don't think you can expect younger devs to keep maintaining
daddy-o's web framework crap and cleanup the mess left by Java heads.

However, I don't want to sound too negative. I can see a perspective for the
JVM (Graal/Truffle) as a polyglot runtime where most of the ancient Java stuff
is hidden from you, and you're using JavaScript or other non-JVM-only language
as a migration strategy to get rid of Java alltogether in the distant future.

~~~
lmm
> Where maven dropped the ball is the myriad of maven plugin magic, maven's
> implicit lifecyle, and a pom.xml's Turing pits, etc.

Could you be a bit more concrete? I don't recognize any of your descriptions
in my experience of maven.

There are probably some bad plugins out there, but as in any system the
solution is not to use them.

The complete lifecycle is listed in the documentation, and it's all very
common-sense.

pom.xml isn't meant to be Turing-complete, and if you try to use it like a
Turing-complete build language you will get yourself in trouble (as many of
the early Ant diehards did). You need to treat it as a declarative config
file, no different from e.g. Cargo.toml.

> I just don't have the patience with wading through crap that 2003ish Java
> nerds thought would be a good idea. And increasingly, as Java libs get EOLd,
> this will be a major problem for monolithic Java apps with tens of
> submodules. I don't think you can expect younger devs to keep maintaining
> daddy-o's web framework crap and cleanup the mess left by Java heads.

It's just the opposite. I don't expect anyone to want to maintain Ant or
Gradle builds in the future, since they can have any kind of crap in them. But
Maven builds are forced to be kept sensible; the tool just isn't flexible
enough to let you put crap in your build definition, by design. (If you really
insist on doing crap you can make a crappy plugin, but your plugin is then
forced to be versioned, tagged in VCS etc., so stands a better chance of being
picked up by your organisation's normal code quality efforts).

~~~
tannhaeuser
I may be biased by doing freelance work (eg. seeing only crap projects), but
almost all customers struggle with fckn maven: migrating freaking jetty-maven-
plugin, servlet api versioning conflicts, ad-hoc scripting using ant plugin,
shading/fatjar plugins, multiple mvn central listings for the same artifact,
fragile local dependency resolution, dozens of pointless submodules. A
customer of mine even had a solid 3 week outage when they wanted to setup a
product for blue/green deployment based on maven. Makes autotools look like a
sane build tool.

~~~
lmm
> migrating freaking jetty-maven-plugin

There's a jetty-maven-plugin? What for? When I use jetty I treat it as a
library, embed it in my application, write my own main() and then my
application is just a normal application.

> servlet api versioning conflicts

> multiple mvn central listings for the same artifact

These are a genuine problems but they're ones that every mature ecosystem
struggles with. Maven has better tooling than most IME - you can use the
enforcer plugin to require dependency convergence, and when multiple packages
contain the same API you can put exclusions in a common parent. No ecosystem
has really solved the problem of package renames nicely, IME.

> ad-hoc scripting using ant plugin

Yeah don't do that. If people will insist on shooting themselves in the foot,
there's only so much you can do to stop them.

> shading/fatjar plugin

What went wrong there? IME the shade plugin is very good. There are a couple
of inherent JVM-level limitations (having to specify transformers for service
locator files etc. because of the way the JVM spec is written) but it's hard
to imagine any other build tool could do better.

> fragile local dependency resolution

Not my experience at all - what specifically goes wrong?

> dozens of pointless submodules

Submodules are cheap. IME when coming to work on a new project it's much
easier to understand the build/dependency structure if there are lot of
submodules rather than a complex build - e.g. rather than trying to have a
custom build phase for generating some RPC stubs or whatever, it's fine to
just have them in their own submodule and then it's obvious to the reader what
the dependency graph looks like. What's the downside?

> A customer of mine even had a solid 3 week outage when they wanted to setup
> a product for blue/green deployment based on maven.

What? How?

> Makes autotools look like a sane build tool.

Strongly disagree with that one. Autotools has several layers of
template/macro expansion that all seem to do much the same thing (so why not
just one?) and encourages builds that use arbitrary unversioned command line
tools from the host system, meaning you very rarely get reproducible behaviour
on a host with a different setup. Maven gives consistent, declarative builds -
what's not to like?

------
azhenley
The most interesting new feature I think is the Shenandoah GC. The summary
from [1]:

"Add a new garbage collection (GC) algorithm named Shenandoah which reduces GC
pause times by doing evacuation work concurrently with the running Java
threads. Pause times with Shenandoah are independent of heap size, meaning you
will have the same consistent pause times whether your heap is 200 MB or 200
GB."

The original algorithm was published in 2016 [2]. It consists of 4 phases:
initial marking, concurrent marking, final marking, and concurrent compaction.

[1] [http://openjdk.java.net/jeps/189](http://openjdk.java.net/jeps/189)

[2]
[https://dl.acm.org/citation.cfm?id=2972210](https://dl.acm.org/citation.cfm?id=2972210)

~~~
_bxg1
GC pauses have been one of the major barriers to using garbage collected
(read: higher-level) languages for game development. This could open up the
JVM for games, which could have some exciting implications.

~~~
stefan_
Their lower end target is 10 ms. In a game, 16 ms is your entire time budget.

~~~
spricket
10 ms isn't all that much. When games load in assets they'll do various things
like malloc huge chunks and you lose a few frames.

If GC only causes occasional (maybe every 2 minutes) loss of a frame or two it
should be no problem. If you watch benchmark FPS traces that count every frame
delay you'll see that occasional stutters happen in basically every game.

Loss of a single frame just isn't noticeable

~~~
blattimwind
> When games load in assets they'll do various things like malloc huge chunks
> and you lose a few frames.

Streaming/Loading assets in the main render thread is a very 2005 thing to do.

~~~
vvanders
Yeah, the whole reason you have pools and arena allocators is so that you
don't do small/large malloc mid-frame. Perf 101 is don't malloc during regular
gameplay.

------
hyperpallium
Switch expressions prepare the way for pattern matching
([https://openjdk.java.net/jeps/305](https://openjdk.java.net/jeps/305)),
instead of `instanceof` checks and casts.

But (in my naive opinion) double dispatch seems a more elegant and java-ry
solution, i.e. polymorphism on argument classes, so different methods are
invoked for different object _runtime_ classes (instead of using the
_compiletime_ type of the variable).

The switching could be optimised, as ordinary polymorphism is in the JVM.

Sure, you'd wreck legacy code if you just introduced it, but there's surely a
backcompatible way to do it that isn't too awkward.

BONUS: goodbye visitor pattern!

~~~
aardvark179
That kind of multiple dispatch would be far more disruptive at several levels,
and still wouldn’t really get you where you want to go without a lot more
compiler and JIT magic.

Sure, you could match on types, but you wouldn’t be able to extend that to
destructuring patterns, or regsxps as patterns on strings, or so many other
ways patterns may be extended in future releases.

~~~
hyperpallium
My comment's a little out of place. I'm not against pattern matching, but for
double dispatch; we can have both.

Their initial motivating examples was bare _instanceof_ , but I now see they
extend it.

How would destructuring fit this model ?!

~~~
aardvark179
Brian Goetz has writes quite a bit about ongoing projects. The latest article
he has done about pattern matching is I think
[http://cr.openjdk.java.net/~briangoetz/amber/pattern-
match.h...](http://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html).
There is a load of stuff in there about destructuring patterns from about half
way down.

~~~
hyperpallium
Thanks, a methodical article! Not keen on special support required for
destructuring. Nice that they discuss Visitor pattern (and the switch example
for such cases looks nice). They don't dicuss double dispatch - but not
relevant to them.

------
darksaints
Anybody know how the graal project ties in with all of this? Is oracle
effectively developing 3 different JVMs (OpenJDK, Oracle JDK, GraalVM)? Or is
there some sort of convergence plan?

From what I understand, graal has made a lot of headway with language interop,
as well as a handful of specific memory optimizations and native compilation,
but overall is lagging in pure throughput/latency performance behind hotspot.
It would be really cool if we could get the best of both worlds.

~~~
aseipp
Oracle JDK is just the Oracle(TM) Supported branding of OpenJDK, now. As of
Java 11, there are no feature parity or real technical differences between
OpenJDK or OracleJDK, just support/EOL differences from vendors. So, that's
pretty simple.

GraalVM is... complicated. There are a few parts to it:

1) An advanced JIT compiler, written in Java, and distributed as ordinary
maven/jar packages, etc. You can use it yourself if you want. Interestingly,
this compiler package ("graal") can be used for the JVM itself, and it will be
used to compile the Java code that is run by the JVM. The "JVMCI" feature
allows you to plug third party compilers into the JVM and replace HotSpot, and
Graal (the library) is such a replacement. You can use this compiler on
ordinary OpenJDK 10+ with a special startup invocation.

2) Truffle, which is another library for writing programming language
interpreters. It does a lot of magic to make them fast. It uses the graal JIT
compiler to do this, so it depends on the previous library.

3) A bunch of programming language implementations under umbrella: Python, JS,
etc. These are implemented using Truffle. By using Truffle, these language
implementations magically share an object model (so they can interoperate),
and they get a JIT compiler, based on Graal, for "free". This means the
languages can interoperate and JIT together cleanly (the compiler can inline
JavaScript into Ruby!)

4) If you use Graal as the JVMCI compiler (i.e. for your host Java code), and
you use Truffle-based languages -- Graal can extend benefit #3 to the host
Java code itself. This effectively means the JIT compiler can inline and
optimize code across every language boundary.

5) SubstrateVM, which is is a tool to turn Java programs into native exe
binaries. The intent is you use SVM on the programming language interpreters,
to produce interpreter binaries that look "normal" to the user. These binaries
are run on custom, non-JDK/HotSpot runtime. The Java code is not JITed, but
interpreted code -- Ruby, Python, JS, etc -- is. (This means you have benefit
#3, but not #4). SubstrateVM uses a custom generational garbage collector
(written in Java!)

6) The "GraalVM distribution", from graalvm.org. This is a combination of all
the above pieces together as a sanctioned package. This package uses JDK8 as
the base virtual machine.

7) The GraalVM distribution comes in both a "community" and "commercial"
edition, which do have technical/feature differences.

Here's the thing: you can use everything from 1-4 with an "ordinary" OpenJDK
today if you know what you're doing, and you don't need a special JDK build.
SubstrateVM might also be workable, but I don't know.

Points 6-7 actually mean that there is generally a difference between "GraalVM
the platform" and "Graal the compiler". Notably, while OpenJDK no longer has
feature gaps vs the commercial OracleJDK, GraalVM _does_ , which I find a very
weird choice on Oracle's behalf and unfortunate, but maybe it will change one
day.

If you want to use one of the new low-latency garbage collectors
(ZGC/Shenandoah) with Graal, I don't think that's possible as of right now:
garbage collectors need to interface with the JIT compiler, but ZGC does not
support the JVMCI interface (it will explode on startup), and Shenandoah
doesn't either, I believe (but maybe this changed). This will almost certainly
be fixed in the future, of course.

~~~
darksaints
Thanks, this is a really useful overview, and also explains why I always seem
to get so many different explanations as to what graal is.

------
stygiansonic
Included is JEP 230, a Microbenchmark Suite. It's based off of JMH. Nice to
see this included!

[http://openjdk.java.net/jeps/230](http://openjdk.java.net/jeps/230)

[http://openjdk.java.net/projects/jdk/12/](http://openjdk.java.net/projects/jdk/12/)

------
geophile
Are they _ever_ going to release value types?

~~~
MrBuddyCasino
Yeah that was supposed to be in 12 wasn't it? Everyone is waiting for that, it
will obsolete Lombok.

~~~
aardvark179
No feature is meant to be in a release. A feature will be done when it’s done,
though features may be split so that some functionality can land earlier.

------
crooked-v
Still nothing to handle checked exceptions in streams properly... sigh.

~~~
vbezhenar
I wonder why they didn't use generic exception type in their
java.util.function classes. That would propagate checked exceptions
statically.

Something like

    
    
      @FunctionalInterface
      interface Function<T, R, E extends Throwable> {
          R apply(T t) throws E;
      }

~~~
Viliam1234
In Java, the concept of exceptions is incompatible with the concept of
parametrized types.

During compilation, type parameters are erased. "T" becomes "Object"; "T
extends Something" becomes "Something"; assignment becomes type conversion.
But at the end it works correctly. If you try to make something that wouldn't
survive the type parameter erasure -- such as having two methods with the same
name, one of which accepts "List<String>" and another accepts "List<Integer>"
as their input -- it will be a compile-time error, because you can't have two
methods with the same name and the same parameter "List".

But imagine that you have a type "MyException" extending RuntimeException, and
your code has "catch (MyException)". After compilation, this would become
"catch (RuntimeException)", which is wrong, because it would also catch other
RuntimeExceptions, and it is not supposed to. But if you make this
construction a compile-time error, then... the whole thing becomes useless,
because what's the point of having an exception type you cannot catch.

~~~
vbezhenar
The entire concept of checked exceptions is compile-time, because there's no
checked exceptions in JVM. I don't really understand your argument. I'm not
suggesting to catch exception of generic type, it won't be possible indeed,
but it's not required either. You just need to tell compiler to pass "throws"
via generic type. You can declare your map function with generic throws and
compiler will respect that.

------
connorlwilkes
The new switch feature looks nice, the way it previously used to work was so
unwieldy.

~~~
azhenley
In case someone is curious what it looks like with the new -> form:

    
    
        switch (day) {
            case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
            case TUESDAY                -> System.out.println(7);
            case THURSDAY, SATURDAY     -> System.out.println(8);
            case WEDNESDAY              -> System.out.println(9);
        }

~~~
_old_dude_
or using the switch as an expression

    
    
      System.out.println(switch(day) {
        case MONDAY, FRIDAY, SUNDAY -> 6;
        case TUESDAY                -> 7;
        case THURSDAY, SATURDAY     -> 8;
        case WEDNESDAY              -> 9;
        });

~~~
melling
That's much nicer. Anything else added to Java recently to reduce the
boilerplate? I haven't used Java much in 5-6 years. Glad they are iterating
faster.

~~~
spricket
As another poster mentioned, the new type inference is great. So is lambda
support. Another is Lombok.... Yeah it's not official but we use it literally
everywhere and it helps a ton with data classes especially.

Nullaway and a bunch of other linters will also save you from accidentally
falling in one of the dusty corners.

RxJava and Java Streams are also very nice.

Anonymous classes are nice too I guess (although they're fairly limited).

Overall the java experience has improved massively in the last 5 years, but
you need to know where to look. Highly recommend the two popular "awesome
java" repos on GitHub for an overview

~~~
jacques_chester
The .parallel() method in Java Streams is basically one of my favourite magic
spells ever.

~~~
spricket
Ah yes, parallel stream(), for when you need to filter a list of 13000 entries
for.... Reasons. Bad reasons.

Use it all the time :)

~~~
jacques_chester
I tried it once on a simple monte carlo thingy and legitimately said "wow!"
out loud when it just worked.

God, all the _fussing_ with threads and fork-joins and mapreduces and god
knows what everyone else wanted me to do: gone. Gone!

~~~
spricket
Yeah seriously Java's threading support is good but the boilerplate was
horrific.

One thing you should know is that parallel streams use default thread pool
unless you specify otherwise. Had that choke up some REST handler threads a
few times. If you think it might be an issue make sure to specify a different
pool

------
ocdtrekkie
Meanwhile, most enterprise apps still seem to only work with JRE 8. And those
which I know of have elected to replace Java rather than upgrade.

~~~
lucb1e
8? I see more 7 or even 6. Until recently I actually thought 8 was the latest
until I needed to develop a small project and discovered we were at 11.

Actually, looking at the version history, I guess it's not weird that I
thought 8 was pretty recent, as until 1.5 years ago (Sept '17) it was actually
the latest and it is still supported until 2020 (unlike 9 and 10).

    
    
        v6  2006
            2007
            2008
            2009
            2010
        v7  2011
            2012
            2013
        v8  2014
            2015
            2016
        v9  2017
        v10 2018 
        v11 2018 again
        v12 2019

~~~
user5994461
Java 8 is supported until 2023.

Funny enough, Java 11 will be end of life the following year. It's not even
worth migrating to, better jump to java 15 then.

[https://access.redhat.com/articles/1299013](https://access.redhat.com/articles/1299013)

~~~
kristianp
Java 11 isn't worth migrating to because it's end of life is 2024, more than 5
and a half years from now? That's a little extreme.

------
otisg
Great to see Java 12 (and the shorter release cycles) but how quickly do
people actually move to newer Java? Here's a poll with some results:
[https://twitter.com/otisg/status/1108093046397247488](https://twitter.com/otisg/status/1108093046397247488)
(still open, please vote so there is more data)

------
imhelpingu
I wonder if they might condescend to utilize the JVM so I don't have to
compile JMC myself for another 5 months, or maybe at least they'll remove
their circular links that infuriatingly obscure the fact JMC binaries don't
currently exist. For the past 5 months.

------
wink
I wonder if they'll fix the performance again. I'm mostly peripheral to
clojure-land and 8 still seems to be the best choice.

------
vbuwivbiu
presumably there's still primitives and boxing ?

------
java-man
I wish they did not decouple JavaFX...

~~~
samus
Yeah, that kinda makes it impossible to become a successor to Swing. But the
situation actually got more sane because JavaFX can be included now as a Maven
dependency, like any other framework.

~~~
james_s_tayler
Why do people still use Maven when Gradle exists?

I'll never know.

~~~
pjmlp
Because Maven doesn't require a background daemon eating 2GB of memory to be
fast and IDEs can actually provide code completion and documentation while
typing.

Android is the only reason to have to put up with Gradle.

~~~
ptx
Gradle 5 lets you write the build scripts in Kotlin, which is supposed to
address the code completion issue. (And the continuous build mode is a nice
feature!)

But, yes, is does use a lot of memory.

~~~
pjmlp
So I have to use additionally 2GB, adopt yet another programming language, to
get back what Maven already gives me out of the box?

Eclipse and Netbeans compile on file save, can't get more continuous than
that.

------
hestefisk
I’m missing the TL;DR on what language features may be introduced. Any ideas?

~~~
stygiansonic
Check out the OpenJDK page:
[http://openjdk.java.net/projects/jdk/12/](http://openjdk.java.net/projects/jdk/12/)

------
ilovecaching
I understand why Java has to keep on chugging along, but I feel bad for the
people that have to be a part of it. It's like watching people keep coal
trains going while people are moving to cars.

Why? Besides being owned by Oracle, which is enough of a reason to never use
Java ever again, it's also lost the niches that brought it into existence.
Java no longer runs everywhere. Java on the web is dead, and you can now write
ubiquitous apps in basically every language. There's no reason to deal with
the JVM and it's domain knowledge when you can write a nimble Go app for your
backend and a Javascript app that will run on mobile, web, or desktop. A VM
language? You mean v8 sandboxing and web workers; WASM which lets me write C,
C++, and Rust all of which can talk to Javascript APIs. All of my services are
stateless and ephemeral. Crashing is expected, and I can use host monitoring
tools instead of introspecting the JDK. On the cloud it gets even worse for
Java. Why use a meaty framework like Spring when I want to just spin up a
bunch of micro services, or have an API gateway kickoff a bunch of lambda
jobs.

Java also took OO in so many terrible directions. OO defined by it's creator
looks nothing like the enterprise OO that big business sold to commoditize
programming, which now only exists as a ball and chain on legacy systems.

One day Java will be like Cobol. There's probably a lot of money for Java
developers for many more decades, but god I do not envy anyone that has to do
it.

~~~
hota_mazi
> it's also lost the niches that brought it into existence

Applets, JavaBeans, and CORBA. What a loss.

> Besides being owned by Oracle, which is enough of a reason to never use Java
> ever again,

That stopped being an issue years ago. OpenJDK is a thing, you know?

> Java on the web is dead,

I don't think you have any idea about the hundreds of millions of lines of
Java that power the web as you know it today.

The rest of your post is filled with equally uninformed claims but I'm going
to stop here.

~~~
ilovecaching
Java on the web is a reference to applets running in the browser.

Yes, Oracle, the company that sues people for breathing the same air owning
Java is an issue.

Maybe I am uninformed, but you haven't made a good case that there's any truth
to that.

~~~
jm4
Do you know anything about Java? I'm not trying to be insulting. Java has its
problems, but your points are so far off the mark. Applets haven't been a
thing for 20 years and I'm not sure they were a thing then either. Do you know
people make web apps in Java and there's a ton of quality open source
libraries out there?

~~~
ilovecaching
I developed Java (Swing, Spring, JavaFX), managed tomcat deployments, good
stuff.

I think my question is, do most Java developers really know what goes outside
of their window? Every language has a good story for web apps these days. The
web is ubiquitous. You can write in Phoenix, Cowboy, Rails, Sinatra, Express,
"net/http", Django, Laravel, Flask, Rocket... Java is literally middle of the
pack at best. So that's not a compelling reason to use Java. So then we have
to look at the rest of Java. Is there anything else in there that would make
it better for web dev than a simple Go/Ruby/Python/Javascript/Rust/Elixir app?
No? Ok, then let's not use Java. Java excels at being mediocre at everything,
but the best at nothing.

~~~
pjmlp
We rather enjoy the state of the art IDEs, JIT and GC compilers from Java and
.NET, while slowly enjoying watching hipster startups rewrite their stacks
when customers come flooding in.

Ask Twitter how their Rails apps is holding on.

