C compilers were between K&R C and ANSI C, writing portable code was #ifdef mess.
C++ compilers were even worse than C ones. Each between their own interpretations of CFront, C++ ARM and ongoing work at ANSI.
Outside UNIX world, no one cared about POSIX, which was in adoption phase anyway. So even across UNIX systems, #ifdef spaghetti code it was.
Safe system programming languages like Ada, Modula-2, Modula-3, Oberon were failing to pick up steam with the enterprise adopting UNIX variants and its two main languages C and C++.
Java brought sanity into writing portable code and better type safety.
The initial versions were surely slow, but the adoption of JIT and AOT compilation across commercial JVMs helped to adopt it.
As for the ivory towers that get written with Java, they were being written in code generators based in UML/OMT/Booch..., C, C++, Clipper and lots of 4GLs when it appeared.
It is just an enterprise sin to write such type of software.
First System, Second System, Third System.
Right now Java is slowly moving to the Third System (see the evolution from J2EE => JEE 5 => JEE 6 => JEE 7). Ditto with the mindset of Java developers of today.
edit: I suspect that none of the downvoters ever implemented a single compiler targeting JVM.
Is there a good reason for VMs to support TCO rather than having compilers perform it?
> no (optional and confined) unsafe pointer arithmetics
When do you want this? There's sun.misc.Unsafe#setMemory if you really need it.
> no value types
Might be added in JVMS 10 or some version thereafter.
> a pathetic limit on a method size makes it an extremely shitty target for any language other than Java.
True.
> All the existing languages running on top of JVM are very, very inefficient, or have to pay a horrible price for being able to run reasonably fast (crap like `recur` in Clojure, for example).
Fair enough, but it wasn't designed as a general purpose compilation target like llvm.
Again this word! Proper tail calls handling is not an "optimisation". Optimisations are supposed to be optional, while tail calls handling makes a semantic difference.
And, no, compilers cannot do it statically. You cannot statically resolve virtual calls, for example. Consider the following trivial case:
`(define (f g x) (g x))`
> When do you want this? There's sun.misc.Unsafe#setMemory if you really need it.
Try implementing, say, an STG efficiently. Or even a WAM.
> Might be added in JVMS 10 or some version thereafter.
JVM may start to suck less at some point. But now it sucks.
> but it wasn't designed as a general purpose compilation target like llvm.
Exactly. And that's why it's inferior to the other VMs, which were designed with multiple source language semantics in mind. Including even CLR.
Due to the way JVM does bytecode verification. It will be fixed in future versions
https://www.youtube.com/watch?v=2y5Pv4yN0b0
> no (optional and confined) unsafe pointer arithmetics
www.docjar.com/docs/api/sun/misc/Unsafe.htm
Will be replaced by an official API in Java 9.
> no value types
http://openjdk.java.net/jeps/169
> pathetic limit on a method size makes it an extremely shitty target for any language other than Java.
Java Virtual Machine
In CLR you can selectively switch off the verification.
> www.docjar.com/docs/api/sun/misc/Unsafe.htm
I do not want an inefficient API. I want a low level functionality which can be mapped efficiently to what the real hardware does.
> http://openjdk.java.net/jeps/169
> This work is not intended to change the Java Language Specification or JVM bytecode instruction set.
Okay... It's not going to be anything useful.
> Java Virtual Machine
And that's exactly why it sucks. There are much more universal VMs out there.
Why open the door to security exploits?!
C derived languages are already enough.
> I do not want an inefficient API. I want a low level functionality which can be mapped efficiently to what the real hardware does.
Ever heard of intrinsics? Just because it looks like a method call, doesn't mean it is one.
> Okay... It's not going to be anything useful.
The final form is still ongoing work.
> And that's exactly why it sucks. There are much more universal VMs out there
Except for the CLR, I don't know any other.
The universal VM has been pursuit since UNCOL was presented to the world.
Why limit your VM expressive power? Restrict only untrusted loadable modules, do whatever you want in the trusted realm.
> C derived languages are already enough.
Not nearly. You won't have a managed VM with fast run-time code generation with C.
> Just because it looks like a method call, doesn't mean it is one.
Problem with intrinsics is that the majority of your optimisation passed do not know anything about them. See LLVM as an unfortunate example. Most of the SIMD intrinsics are not even used in a simplest constant folding there.
> Except for the CLR
Bingo! CLR is better. Scrap JVM.
I was speaking about security exploits. C should never have happened.
> Bingo! CLR is better. Scrap JVM.
Yes the CLR does quite a few things better than the JVM compatible VMs do currently.
However, the JVM being a specification means I can find a JVM for anything has that a CPU, from smart cards up, servers, mainframes, cars, weapon guiding systems, factory robots, anything.
So while technically better than the reference implementation, it doesn't cover the application spectrum JVM compatible VMs do.
People tend to forget that Sun (now Oracle) JDK is just the reference implementation.
Note I use both eco-systems since the beginning.
I see. I sort of agree - C should never have been exposed to the programmers. But a C-level VM is an extremely useful thing for implementing high level languages. I'd rather move safety checks a number of levels up, and leave VM level to performance-related stuff.
And both Microsoft and Oracle are realizing this.
.NET has native compilation on WP, with .NET Native coming on .NET 5. NGEN is a very simple compiler just for optimizing startup time.
Java always had AOT compilers in commercial JVMs, but not on Sun.
Now Oracle has SubstrateVM, and there are plans for AOT compilation at least in Java 10 timeframe.
And the difference between abstract machines, intermediate representations and virtual machines is very elusive (see all the confusion around LLVM for example).
The JVM worked well enough and a lot of companies put a lot of effort into it. But fundamentally, the design is "meh". It just gets the job done.