Being close to the machine is a very desirable property for platforms. It is not unique to C and C++. Lisp had it in the 80s. It still has it now but nobody uses Lisp unless it is Clojure.
The urban dictionary defines “Flying Low” as a euphemism for having your zipper down, but that’s not what I have in mind.
A platform that flies low is a platform that keeps the distance between the programmer and the CPU short.
A formal-esque definition:
Flying low is the property of having a small number of easily understandable layers of abstraction between the platform and the machine.
Assembler flies low. It has a one-to-one mapping to machine language, one level of abstraction that is very easily understandable. If there is an OS between the resulting executable and the machine, then there are two layers of abstraction. It is almost impossible to completely understand an operating system, but for the purpose of this article we will assume that we have a basic understanding of what an OS does.
C flies low. A compiler can get pretty complicated, but the general process is really easy to understand.
C++ has a lot of additional expressiveness on top of C. Classes, lambdas (C++11 FTW), etc. However, for the purposes of this article, expressiveness and abstraction are different things. C++ is more expressive than C. It does not have more layers of abstraction because there is only a compiler and an OS between C++ code and machine instructions.
A C++ compiler is much more complicated than a C compiler and therefore more difficult to understand. By definition, C flies a little lower than C++.
Java code has two layers of abstraction. A virtual machine and the OS. The JVM is an obscenely large system with almost two decades of development effort. There is not a single human capable of understanding the JVM. The closest we can get is Cliff Click. But you are not Cliff Click (unless Cliff is reading this… in which case, Hi Cliff! Big fan here.)
The JVM is such a thick layer of abstraction that it makes Java very hard to port. Dalvik is a good example that porting the Java platform requires a rewrite (and potentially, an army of lawyers). Rewriting a 20-year old system is a very inefficient pursuit. As such, it should be scrutinized so that we know if it is worth the tremendous effort.
A note on language productivity: I can’t dispute the fact that the more expressive the language, the quicker it is to implement a system. I can however argue that a C++ programmer and a Java programmer of equal skill will finish the same task in roughly the same time, but instead of backing up my claim I will make the argument moot by pointing out that it is an objective truth that variation in programmer ability is vastly more important for implementation time than the choice of language. Don’t pick languages, pick colleagues…
So why is Android development done in Java?
Garbage collection is a necessity in languages like Lisp and Haskell. These languages are very highly abstracted. They are a different breed.
I don’t have the money to legally read the current research on language productivity, but from my experience and the opinion of a lot of programmers I respect, I have confidence in that garbage collection is not in itself a productivity booster. It is an enabler of features that boost productivity, but those are largely not featured in languages in the power spectrum of C++ and Java.
No buffer overflow attacks when your Java app crashes. Is this really a problem in a walled garden? The future will be filled with walled gardens and inside walled gardens, crashes are just crashes. It doesn’t matter if you get a core dump or a VM message. Actually, the lack of a behemoth VM makes crashes and memory problems much more debuggable.
Java is more type-safe than C++. Is this advantage important enough to trade performance and control?
Another advantage that Java usually has over C++ is libraries. I don’t know if this is also the case for Android. I’m guessing Yes, but only because Android has been around for a while now.
What killer advantage does Java have to justify the complexity of Dalvik? Write once, run anywhere? One would think the 90′s would have made us learn…
Garbage collection? No. Sandboxing? No. Libraries? Debatable, but not a killer advantage
Android should have shipped with a native API and a Java layer on top. Hell, why not a Python layer on top? Now we are paying for that mistake with a painful to use NDK.
Why is it important to fly low?
The Python platform has two levels of abstraction. It has an interpreter and an OS. The interpreter is a hackable black box. It is easy to drop from Python to C and it is easy to drop from C to Assembly.
Python flies low and Java doesn’t. What advantages does flying low give python?
For one, I can download a zillion Python interpreters for my iPad. Substitute python for lua, which flies even lower and you can have lua running on your big-ass game engine bending the Apple A6 to your will; with zero extra effort.
Flying low allows a platform to be nimble. To move from host to host. This is important now more than ever because the line that defines what a computer is is blurring every day. Nimble platforms survive on their own. Big fat platforms take big companies and huge teams to survive Think early mammals vs dinosaurs.
I know what you are thinking. You are asking yourself “How do I make my platform as immovable and fat as possible?” Welp, it’s easy! Just add a JIT.
They did it to Python with PyPy. It runs way faster on my Desktop! On my Desktop, which is the only place I can run it. (Shut up, I know there’s an ARM backend, I’m trying to make a point here)
Take a bunch of PhDs and ask them to implement a JIT for your dynamic language. Wait a couple of years and you’ll end up with a dramatic increase in performance and a black box which few can penetrate. You will cast yourself out of the App Store in the process, by the way… at least until Apple decides that modifying the Program Counter is alright with them.
Jitting is very, very interesting. But if you want performance, use C. If you want quick iteration, use an interpreted language. You can use both and get the best of both worlds. Just make sure you are flying low.
Yet JS is everywhere. It is an curious counterexample of a nimble platform that flies high. In my defense, JS is like the Cantor Set; it’s usually used as a good counterexample. If you are willing to sacrifice performance, then a nimble platform that is far away from the machine is good enough for the purpose of portability.
There is something true about all new shiny hardware. It has a C API. If they are stupid enough to not expose it, they will do it soon enough. Make sure you use a platform that flies low so that you can pack your bags and move whenever you please.