I was reading through a Java book by author Herbert Schildt and he writes how the advantage of Java over C++ in portabilaty is that while C++ can be run anywhere, it still requires each program to be compiled with a compiler that was created for that CPU, and creating compilers is difficult, while Java doesn't need to be compiled for each CPU as long as there is a JVM for that processor.

My question is how is this an improvement? Doesn't the JVM need to be compiled for each architecture anyway, so you still require a individual compiler for each type of CPU? So what is this advantage?

  • 2
    I don't have to compile the JVM on every platform, someone else has already done it for me. This means I can just distribute my Java programs as is, and they'll be supported by every platform with a JVM. – Vincent Savard Jan 6 '17 at 19:12
  • 2
    Of course, but the point of having a virtual machine is that you have a program that's supposed to run Java code the same way on every platform. The effort to make it work that way happens once per platform instead of once per application per platform. That's the theory, anyway; people do manage to write broken VMs, though. – Blrfl Jan 6 '17 at 19:34
  • 1
    See this article on the subject. – Servy Jan 6 '17 at 20:23
  • 3
    Write once, debug everywhere. – Basilevs Jan 6 '17 at 22:04
  • 1
    In practice someone else has made the compiler already, but for you the application developer there's still a benefit, because you still don't need to compile your program for different CPU architectures. – immibis Jan 8 '17 at 8:44
up vote 8 down vote accepted

The advantage to you is that if there is already a good JVM for of all your target platforms, all you really need to do is release your Java application once and it should just run on all of them. You shouldn't need to do anything else!

...of course, that's the theory. In reality, you probably should test on each target platform before releasing. Just in case your application depends (intentionally or accidentally) on OS-specific functionality.

With C++, it's up to you to ensure that you compile your application separately for each platform, with the appropriate platform-specific compiler and libraries. And then test for each one.

The advantage that Java could give you here goes away if there is no suitable JVM for your target platform.

  • 1
    Your answer gives IMHO a wrong impression. In reality, I am pretty sure the majority of portability issues in Java programs are not caused by different JVMs, but by differences in the underlying operating systems and hardware - JVMs cannot decouple the programs completely from these. So one does not just have to test on each platform, but actually remove the portability issues. – Doc Brown Jan 6 '17 at 20:28
  • 4
    @DocBrown This is only true when your code depends on operating system functionality. This is the fundamental reason behind why Java UIs have been so disapointing. If you stick to the functionality defined in the JVM spec and use a compliant JVM, you won't have portability issues. I've run the same code (much of which was not written by me) on Windows, AS400, Linux, AIX with 0 issues many times. – JimmyJames Jan 6 '17 at 22:07
  • @JimmyJames: you got me wrong, I am not saying you cannot write portable code (if you know what you are doing). However, I think it is much more likely to accidentally make your program depend on OS or hardware specifics than accidentally making it depend on JVM specifics. – Doc Brown Jan 7 '17 at 0:08
  • 1
    @DocBrown: the JVm being unable to decouple the program from the OS is a failure of the JVM's (Or Java's, or Sun's, etc) promise. It is supposed to provide that decoupling. – whatsisname Jan 7 '17 at 23:51
  • 2
    @whatsisname: well, the AFAIK the primary purpose of the JVM is to decouple from the underlying processor architecture. The decoupling from the OS is part of the JRE. But you are missing my point. It is very simple to create a Java program which is not portable, for example, by trying to run an external command which is only available on one OS, and not on the other. That is not a bug of the JVM or the JRE. – Doc Brown Jan 8 '17 at 9:18

If you have 10 programs and 10 platforms, you need 100 binaries for C++ (compiling each program to each platform), but only 20 binaries for Java (10 of your programs to Java, 10 of the JVM to the platforms … and those latter 10 are probably not even created by you, and the cost for compiling them can be amortized across all the other programs that also target the JVM).

  • 3
    I think you mean binaries. If you have 10 programs and 10 platforms, you need 100 binaries. etc. A port implies rewriting large parts of the source code, which is not needed for the typical C++ program. – Brandin Jan 7 '17 at 19:01

How does Java improve over C++ in the area of portability?

It's also worth addressing this larger question. The two languages have different "portability" goals.

Java has a goal of "write once, run anywhere." It aims to download programs to a wide variety of devices and have them produce the same results. The Java Language Spec and VM Spec go to great lengths to make Java programs portable in this sense. (In practice, there are library bugs that diminish this to "write once, debug anywhere.")

C++ has an unwritten goal of "run fast anywhere" but it's not concerned with producing the same results or avoiding failures. The C++ language goes to great lengths to make programs run fast on a wide variety of devices, but the meaning of C++ programs varies by compiler and target device. This is a different sense of "portability."

Examples of C++ semantics that differ by compiler and target:

  • short, int, and long have differing widths, may be big- or little-endian, may do twos complement, ones complement, or magnitude + sign math, and >> may do a signed or unsigned shift, so integer math produces differing results
  • various cases cause arbitrary Undefined Behavior (which means the compiler is allowed to generate any code, say, fall through to code that produces uncontrolled engine acceleration): using an uninitialized variable, signed integer overflow, oversized shift count, dereferencing a null pointer, out of bounds array access, stack overflow, and type aliasing
  • a statement like a[i++] = f(i++) + i does not have a specified evaluation order so it doesn't have a well defined meaning, and if f() throws an exception, C++ doesn't specify which side effects will have occurred or not, e.g. what i will contain
  • struct packing layout
  • compiler switches change the meaning of the code (e.g. enum size)
  • Note that despite this, C++ guarantees that each integral type will support a specific minimum range (which in turn imply a specific minimum size), meaning that their behavior is always identical when operating within this range (char is at least 8 bits, short and int are at least 16 bits, long is at least 32 bits, and long long is at least 64 bits; signed and unsigned variants of each have the same alignment and width, with unqualified char being... weird). – Justin Time Jan 8 '17 at 3:27
  • 1
    As of C++11, specifically-sized types are also available (intX_t / uintX_t, int_leastX_t / uint_leastX_t, and int_fastX_t / uint_fastX_t, where X is 8, 16, 32, or 64), when needed... but they get a bit wonky on platforms that don't support types whose sizes are a multiple of 8. The exact-size ones only exist if they can be exactly the specified size. The leastX ones are the smallest supported size that is at least X. [And the fastX ones are always wonky; they're generally the platform's word size, or might be least8 if X is 8.] – Justin Time Jan 8 '17 at 3:31
  • 2
    So, even with the types intended specifically to guarantee that they can be treated as the specified number of bits, their size still isn't the same on every platform. ...Suffice it to say, Java doesn't have this issue. – Justin Time Jan 8 '17 at 3:32
  • 2
    A big one IME: Java's String is defined to be encoded in UTF-16. C++ has a character encoding schism where Microsoft likes to use UTF-16 wchar_t strings and the *nix world prefers to use UTF-8 char strings. – dan04 Jan 8 '17 at 6:40

It's less about code and operating systems, more about compiled binaries and processor architectures.

In C++, we can write code that is portable (works on Windows, Linux, and Mac, and on most popular processor architectures i386, amd64, ARM etc.), but the compiler's output is bound to specific combination of operating system and processor architecture. We must compile the program separately for each combination.

In Java, code gets compiled into Java Byte Code. This byte code can be run on Java Virtual Machine (VM) running on any hardware/OS configuration. The VM must still be separately compiled for each processor architecture and OS, but it's always done by VM provider. There are differences between VMs from different providers, so code and byte code is always portable in the context of single VM provider. It's possible to write a Java program that runs on multiple VM implementations, but differences must be taken into account.

In summary:

  1. Single source is easy, single program binary is harder,
  2. Java adds cross-vm-implementation issues to already present cross-os issues.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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