4

Wherein portability is defined generally as the percentage of platforms a language or technology can run on, C/C++ are often cited as being more portable than Java, because a Java application depends on a JVM being present.

But, what prevents a Java application from shipping within a JVM wrapper? Or being transpiled to C/C++ with a supporting framework? (Essentially a JVM, but as a supporting library instead of a wrapper/container.)

Is there a technical issue? A licensing issue? Or, simply that no one has decided to do it!?


Taking a concrete example, consider the 2nd bullet of the first answer to "Why isn't Java more widely used for game development?", which states that:

Most consoles (e.g., 360, PS3) do not have a JVM, so you cannot reuse code from the PC version. It is much easier to compile C++ code to support various devices.

If this claim is correct (with regards to "most" consoles), is the lack JVM for these platforms due to technical limitations? Legal? Political? etc.


When it's stated that Java "can't" be run on game consoles (or iPhones), do we really mean can't!? Or, do we mean, "no one's bothered build the necessary plumbing?"

  • 1
    C being much simpler to implement than Java (or C++) might have something to do with it. And the ability to directly control your memory usage, a rather important capability when KiloBytes is too vague a term for measuring your total memory, or when hardware dictates that data for the Foo widget must be placed specifically at memory address 0xf0. – 8bittree Jan 26 '18 at 18:00
  • "Java application depends on a JVM being present." and a C source code depends on a compiler present for the platform. – Sharon Ben Asher Feb 1 '18 at 8:56
13

Java is portable in the sense that C or C++ can be portable: the same source code can be used for multiple operating systems or processor architectures. In fact this is a lot easier in Java, since the JVM abstracts over many platform-specific details (such as the size of a long int, or endianness), and the standard library abstracts over the functionality supplied by the OS (e.g. how to open a file).

For C and C++, the next best thing is sticking to the POSIX standard which at least gives you source portability across Unixes and Linux, but notably excludes Windows without WSL or Cygwin. And unlike with Java, a portable code base must be be recompiled for each targeted platform. What makes C and C++ “more portable” is that cross-compilers such as GCC tend to have many target platforms (to support a new target platfom, you “only” need to create a new compiler backend).

Java 9 does introduce the possibility to turn a Java application into a self-contained executable that includes any necessary parts of the Java Runtime. But you're still limited by the portability of your JVM. And the package needs to be built on the target OS.

The JVM in itself is a program that may or may not be portable. E.g. HotSpot is a C++ program that can be ported to new OSes or architectures.

But what if we are targetting an embedded device that might not run a full OS or may have hardware constraints? This becomes more difficult for C and Java alike. But there are embedded JREs, and for both classes of languages the solution involves targetting a smaller standard library. Java 9 makes it possible to select modules at build time, rather than having to target a pre-defined profile such as Java ME.

One use case where C wins out is working in absence of an operating system, flashed directly to a microcontroller. You can't use the standard library (e.g. for opening files, or dynamic memory allocation), but the core language is still there. But it is not reasonable to restrict the meaning of “portability” to “can work without the standard library”.

Locked down systems such as iOS or consoles do not allow arbitrary software to be installed, even if they are physically capable of running that software – they are generally built from standard CPUs, using standard kernels. The absence of a JVM on these systems is merely a consequence of the gatekeeper (e.g. Apple or Nintendo) not being interested in allowing a separate platform that is not under their control. So this absence is legal/political.

  • 1
    "Java 9 does introduce the possibility to turn a Java application into a self-contained executable that includes any necessary parts of the Java Runtime." ... Whoa. I should have researched more. I had no idea. – svidgen Jan 26 '18 at 18:48
  • To your last point though, aren't small OS-less systems the problem that Java SE/EE solves? – svidgen Jan 26 '18 at 18:54
  • @svidgen embedded systems are not necessarily OS-less. But yes, it seems that Oracle offers Java ME images that are bootable, i.e. can run without a host OS. Note that SE/EE are the standard and enterprise editions of Java, which are very much not suitable for embedded. – amon Jan 26 '18 at 19:54
  • 4
    @svidgen Java SE still requires 32 MB of RAM and another 11 MB of ROM for the absolute minimum package. That's a huge amount of memory for many embedded systems. For some references, Atmel's AVR microcontrollers have up to 384 KiB of ROM and 32 KiB of RAM. This particular MSP430 microcontroller (PDF link) has 2 KiB ROM and 128 B (note: no prefix, just 128 Bytes) of RAM. A JVM's not going to fit on that. – 8bittree Jan 26 '18 at 20:23
  • @svidgen Java ME (PDF link) is significantly lighter than Java SE, only requiring 128 KB RAM and 1 MB ROM. But that's still too much for any AVRs without expensive external memory. – 8bittree Jan 26 '18 at 20:33
6

a Java application depends on a JVM being present.

That is not true. There is nothing in the Java Language Specification that says anything about the JVM. Oracle is pretty strict about keeping the two separate.

And, in fact, there is a pretty popular mobile phone platform by Google which uses Java extensively without a JVM.

But, what prevents a Java application from shipping within a JVM wrapper? Or being transpiled to C/C++ with a supporting framework? (Essentially a JVM, but as a supporting library instead of a wrapper/container.)

Nothing.

Is there a technical issue? A licensing issue? Or, simply that no one has decided to do it!?

Yes.

Most consoles (e.g., 360, PS3) do not have a JVM, so you cannot reuse code from the PC version. It is much easier to compile C++ code to support various devices. If this claim is correct (with regards to "most" consoles), is the lack JVM for these platforms due to technical limitations?

No.

Legal? Political? etc.

Probably.

Or, just nobody has done the work yet.

When it's stated that Java "can't" be run on game consoles (or iPhones), do we really mean can't!? Or, do we mean, "no one's bothered build the necessary plumbing?"

Apple does not allow apps that can run code that is not part of the app. This would make a pure JVM rather useless.

Note, of course, that you can have an app which includes the application code and a JVM in one app. But, every app would need to have its own copy of the JVM.

  • 1
    "nobody has done the work yet" -- LLVM is able to target output code for both XBox 360 and PS4, I believe, and there are Java compilers available that output LLVM bitcode, and there are available open source Java class libraries that can very easily by compiled for new platforms, so the work is effectively already done. If nobody is using this, it's because there's no desire to do so, not for any technical reason. – Jules Jan 28 '18 at 20:32
2

But, what prevents a Java application from shipping within a JVM wrapper?

I think you got it wrong: if there's a JVM implementation, then the battle is already won, regardless of whether said JVM is shipped separately or embedded with the app. The problem is writing the JVM in the first place.

As an aside, when people talk about "portability", they usually mean "you can recompile this source code with few changes and make it work in another platform", not just "there's a runtime/compiler for this platform" (though, of course, the latter is a requirement). In this sense, Java is as portable as C, which is to say: plain code will likely run as is, but some libraries may be unavailable and some assumptions about memory may be mistaken. Do note that while there's likely a C compiler implementation for almost every platform you can think for, many non-trivial C programs cannot be made to work in another platform merely by recompiling, because of APIs, libraries, memory assumptions and other dependencies.

When it's stated that Java "can't" be run on game consoles (or iPhones), do we really mean can't!? Or, do we mean, "no one's bothered build the necessary plumbing?"

There's no technical reason why Java cannot run on the iPhone, Nintendo Switch or any console. If there isn't a JVM implementation, it usually means there are legal reasons (which is likely the case for the iPhone and for proprietary hardware with official SDKs), or it doesn't make sense because there's already a widely-used SDK with useful libraries for another language, or both.

  • "it usually means there are legal reasons" ... "or it doesn't make sense because there's already a widely-used SDK ..." ... But, is there a legal restriction from the Java/Oracle end that prohibits building compilers and/ VM's or libs to fill the gaps? Or is the latter more likely? ... That, other perfectly sufficient languages already dominate those markets? – svidgen Jan 26 '18 at 20:07
  • I meant legal restrictions from the platform side, not from Oracle. For example, I wouldn't be surprised if Apple or Nintendo didn't want a JVM for their respective proprietary platforms and forbid it. – Andres F. Jan 26 '18 at 20:38
  • ... or maybe they don't forbid it but don't cooperate with third-party devs willing to implement a JVM, which amounts to the same. In any case, the reasons aren't technical :) – Andres F. Jan 26 '18 at 20:48
2

TL;DR: Apart from the legal/business issues others already mentioned, there are indeed technical limitations. Roughly speaking, creating a reasonably good JVM is harder than a reasonably good C compiler. So while theoretically possible, many ports are not created simply due to the effort required.

So what are the challenges? There are at least three important elements of a working Java implementation: support for parsing and compiling the language itself, implementing the standard library, and making the JVM which offers an environment in which compiled applications run.

As for the language, Java has lots of features which C lacks, such as object orientation, lots of validation enforced by the language spec (array bounds checking, bytecode validation before classes are loaded, etc.), a security manager, run-time class loading, a memory model which says quite precisely how multi-threaded code is supposed to behave, and some other obscure features which many develops don't even realize are there but which the language spec describes in great detail. All this causes different Java implementations to be much more similar to each other in terms of program behavior than different C compilers, but it comes at the cost of having to understand and implement lots and lots of features.

Then, there is the standard library which is also quite rich. Most of it is written in Java but there is also some native code used either for performance reasons or because the library works at a low level which is not available directly from pure Java were it not for the libraries (for example the low-level concurrency code).

And finally there is the JVM which is one heck of a monster. It performs lots of operations which are very complex to implement and even harder to implement correctly: garbage collection, just-in-time compilation, class loading and unloading, interfacing with native code while still preserving the JVM's integrity. Have a look at A JVM does that? for a partial list. Implementing all of this while keeping high performance is a very difficult task and there are very few people actually capable of doing it.

Apart from the complexity of implementation, there are also some performance costs. While Java programs can be really fast nowadays, this is possible only thanks to lots of very smart tricks implemented by the JVM. Implementing a JVM without there optimizations would make all programs run slow and thus make the whole port rather pointless. There is also some memory overhead which is hard to avoid. This is not a big problem for a PC or server but for more restricted environments it is. There is also a lot of data that the JVM itself needs: the whole complex standard library. Or the Unicode database which is at least several megabytes in size if I'm not mistaken.

Of course if it is not so easy to make a JVM for a new platform, it is also about as hard to make a transpiler or something that compiles Java to native binaries, as the binaries effectively have to contain the JVM or large parts thereof.

In Java 9, the main focus was modularization which means that for the first time your hello world program might not need to include 50 MB of libraries just for the JVM to start. This is an important step in the right direction but there is still a long way to go before real Java can run in as restricted environments as C. J2ME is actually just a subset of the full Java stack.

1

Size and speed is two huge factors. A JVM is a pretty huge program that needs a lot of RAM and storage space to be used. A JVM is also often slower (depending on the workflow).

This means that Java is not suited for embedded programming (of course depending on how small you think embedded is). For example try running java on a 8 bit microcontroller, for example an arduino.

Edit:

Java Card is subset(!) of java with has a minimum system requirements of 16 kB ROM, 8 kB EEPROM and 256 bytes RAM. While this is small it's not as small as C can manage. It's actually pretty bloated. Java Card uses 16 bit arithmetic which means that it won't run (well) on an 8-bit CPU.

For J2ME the requirements are even bigger, so I leave that one out of discussion.

Please don't downvote this answer without proving my statement wrong, that is show me java running on a highly constraint 8-bit system.

  • 2
    Way off there, see J2ME and Java Card. Java Card is the tiniest of Java platforms targeted for embedded devices. You might tweak your answer a bit ;-) – JGlass Jan 26 '18 at 19:28
  • @JGlass Please show me example of Java running on a 8-bit CPU as I stated in my answer. What I know, Java Card is not able to do that. – iveqy Jan 27 '18 at 10:15
  • 1
    Thank you for the edit - I was just trying to point out that J2ME and Java Card are fairly small - though you're completely right, they won't run on a microcontroller - well I take that back, it might (I thought I had read it a couple times on hackaday.com)Projects - uJ - a micro JVM courtesy of the "man" Dmitry. – JGlass Jan 29 '18 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.