views:

298

answers:

10

I wonder how Java is more portable than C, C++ and .NET and any other language. I have read many times about java being portable due to the interpreter and JVM, but the JVM just hides the architectural differences in the hardware right? We'd still need different JVMs for different machine architectures right? What am I missing here? So if someone writes an abstraction layer for C for the most common architectures, let's say the CVM, then any C program will run on those architectures once CVM is installed, is it?

What exactly is this portability? Can .NET be called portable? There is no official .NET for linux machines, so it is not portable in that sense right?

Edit: Thanks all.. so finally my understanding is that Java is more portable because it adheres to a convention and does not allow stuff that creates hurdles for portability, like i=i++ having no meaning or different meanings on different machines. Java is strict, and this strictness allows the JVM to be written more easily. If you need a CVM, you'd need to either enforce standards on C, in which case it won't be C anymore, or writing the CVM would be extremely difficult as compared to writing JVM because it would have to handle way too many cases. I hope it's close to the right understanding :)

+3  A: 

Java is portable from the perspective of the developer: code written in Java can be executed in any environment without the need to recompile. C is not portable because not only is it tied to a specific OS in many cases, it is also always tied to a specific hardware architecture once it has been compiled. The same is true for C++. .Net is more portable than C/C++, as it also relies on a virtual machine and is therefore not tied to a specific hardware architecture at compile-time, but it is limited to Windows machines (officially).

You are correct, the JVM is platform-specific (it has to be!), but when you say Java is portable, you are talking about it from a developer standpoint and standard Java developers do not write the JVM, they use it :-).

Edit @Raze2Dust To address your question. Yes, you could. In fact, you could make Java platform-specific by writing a compiler that would generate machine code rather than bytecode. But as some of the other comments suggest, why would you do that? You'd have to create an interpreter that maps the compiled code to operations in the same way the JVM works. So the long and short of it is, absolutely, you definitely could, but why would you?

Chris Thompson
I'll write the same comment as above.. what's special about java that a similar VM cannot be written for C or is very difficult to write..?
Raze2dust
@Raze: It would be possible (in fact, C++/CLI is still a (nearly) perfect superset of C, so you could **in theory** compile C code for the CLR), but (1) you lose the raw execution speed C and C++ are famous for (at least until the VM gets as smart as HotSpot, and even then there might very well be an overhead), (2) why?? C in source form can be very portable, and especially in the *NIX world, everyone has a compiler and `make`.
delnan
Years ago someone told me that C was cross-platform compatible, and I replied, "Yes. C is cross-platform in the sense that for any C program that runs on Windows, it is possible to write a C program to do the same thing that will run on Unix. The Unix C code may even slightly resemble the Windows C code."
Jay
+1  A: 

You need the JVM for different architectures, but of course your Java programs run on that JVM. So once you have a JVM for an architecture, then your Java programs are available for that architecture.

So I can write a Java program, compile it down to Java bytecode (which is architecture-agnostic), and that means I can run it on any JVM on any architecture. The JVM abstracts away the underlying architecture and my program runs on a virtual machine.

Brian Agnew
+3  A: 

When you write a Java program, it runs on all platforms that have JVM written for them - Windows, Linux, MacOS, etc.

If you write a C++ program, you'll have to compile it specifically for each platform.

Now, it is said that the motto of Java "write once, run everywhere" is a myth. It's not quite true for desktop apps, which need interaction with many native resources, but each JavaEE application can be run on any platform. Currently I'm working on windows, and other colleagues are working on Linux - without any problem whatsoever.

(Another thing related to portability is JavaEE (enterprise edition). It is said that applications written with JavaEE technologies run in any JavaEE-certified application server. This, however, is not true at least until JavaEE6. (see here))

Bozho
The way I heard the expression was, "Write once, debug everywhere." :)
Robusto
If you are not doing something extreme, this is rarely the case ;)
Bozho
So we still need the specific JVM for that platform right? My question essentially is, Why can't a similar thing be done for C?
Raze2dust
I've written desktop Java apps that run on Windows and Linux with no problem. Yes, there are things that will work on one platform and not another, but they're not difficult to avoid. Like, sure, if you try to read "/etc/passwd" to get a list of users, that's not going to work on Windows. You have to make sure you use the System property for the line ending rather than hard-coding \n versus \r\n, etc. But I don't recall ever having serious difficultly keeping this compatible.
Jay
+1  A: 

The idea is that the Java language is portable (or more accurately, the compiled byte-code is portable). You are correct that each VM requires a specific implementation for a given hardware profile. However, once that effort has been made, all java bytecode will run on that platform. You write the java/bytecode once, and it runs on any JVM.

.NET is quite similar, but with a far lower emphasis on the principle. The CLR is analogous to the JVM and it has its own bytecode. Mono exists on *nix, but you are correct that it is not "official".

Kirk Woll
+4  A: 

Portability is a measure for the amount of effort to make a program run on another environment than where it originated.

Now you can debate if a JVM on Linux is a different environment than on Windows (I would argue yes), but the fact remains that in many cases there is zero effort involved if you take care of avoiding a few gotchas.

The CVM you are talking about is very much what the POSIX libraries and the runtime libraries try to provide, however there are big implementation differences which make the hurdles high to cross. Certainly in the case of Microsoft and Apple these are probably intentionally so in order to keep developers from bringing out products on competing platforms.

On the .net front, if you can stick to what mono provides, an open source .Net implementation, you will enjoy roughly the same kind of portability as Java, but since mono is significantly behind the Windows versions, this is not a popular choice. I do not know how popular this is for server based development where I can imagine it is less of an issue.

Peter Tillemans
+1 - Portability is not a scalar value, and is not determined solely by the need to re-compile.
Andy Thomas-Cramer
great.. that's what I am looking for.. what are these implementation hurdles and hurdles that C creates but Java avoids, and how?
Raze2dust
Java abstracts the runtime environment in the classlibrary and Java language specification spells out in detail how things should behave. Very little leaks out. In C you need to deal with difference between datatypes (what an int is depends on the architecture), endianness of the words, text vs binary files, ..., different standard libraries, ... , it is the "death by a thousand cuts". Library vendors have tackled this with varying success, but as I already mentioned, there are business reasons to keep this from being effective.
Peter Tillemans
+1  A: 

Portability or as written in Wikipedia, Software Portability is the ability to reuse the same software (code) across multiple environments (OSes). The java JVM is a JVM that can be run on any operating systems it was designed for: Windows, Linux, Mac OSes, etc.

On .NET, it is possible to port your software to different platforms. From Wikipedia:

The design of the .NET Framework allows it to theoretically be platform agnostic, and thus cross-platform compatible. That is, a program written to use the framework should run without change on any type of system for which the framework is implemented.

And because Microsoft never implemented the .NET framework outside of Windows and seeing that .NET is platform agnostic, Mono has made it possible to run .NET applications and compile code to run in Linux.

For languages such as C++, Pascal, etc. you will have to go to each OS and build it on that platform in order to run it on that platform. The EXE file in Windows isn't the same as the .so in linux (the machine code) since both uses different libraries to talk to the kernel and each OS has its own kernel.

The Elite Gentleman
+3  A: 

Portability isn't a black and white, yes or no kind of thing. Portability is how easily one can I take a program and run it on all of the platforms one cares about.

There are a few things that affect this. One is the language itself. The Java language spec generally leaves much less up to "the implementation". For example, "i = i++" is undefined in C and C++, but has a defined meaning in Java. More practically speaking, types like "int" have a specific size in Java (eg: int is always 32-bits), while in C and C++ the size varies depending on platform and compiler. These differences alone don't prevent you from writing portable code in C and C++, but you need to be a lot more diligent.

Another is the libraries. Java has a bunch of standard libraries that C and C++ don't have. For example, threading, networking and GUI libraries. Libraries of these sorts exist for C and C++, but they aren't part of the standard and the corresponding libraries available can vary widely from platform to platform.

Finally, there's the whole question of whether you can just take an executable and drop it on the other platform and have it work there. This generally works with Java, assuming there's a JVM for the target platform. (and there are JVMs for many/most platforms people care about) This is generally not true with C and C++. You're typically going to at least need a recompile, and that's assuming you've already taken care of the previous two points.

Yes, if a "CVM " existed for multiple platforms, that would make C and C++ more portable -- sort of. You'd still need to write your C code either in a portable way (eg: assuming nothing about the size of an int other than what the standard says) or you'd write to the CVM (assuming it has made a uniform decision for all of these sorts of things across all target platforms). You'd also need to forgo the use of non-standard libraries (no networking, threading or GUI) or write to the CVM-specific libraries for those purposes. So then we're not really talking about making C and C++ more portable, but a special CVM-C/C++ that's portable.

Once again, portability isn't a black and white thing. Even with Java there can still be incompatibilities. The GUI libraries (especially AWT) were kind of notorious for having inconsistent behavior, and anything involving threads can behave differently if you get sloppy. In general, however, it's a lot easier to take a non-trivial Java program written on one platform and run it on another than it is to do the same with a program written in C or C++.

Laurence Gonsalves
Thanks.. so finally my understanding is that Java is more portable because it adheres to a convention and does not allow stuff that creates hurdles for portability, like i=i++ having no meaning or different meanings on different machines. Java is strict, and this strictness allows the JVM to be written more easily. If you need a CVM, you'd need to either enforce standards on C, in which case it won't be C anymore, or writing the CVM would be extremely difficult as compared to writing JVM because it would have to handle way too many cases. I hope it's close to the right understanding :)
Raze2dust
A: 

WORE - Write Once Run Everywhere

In reality, this is limited to the platforms that have a JVM, but this covers off the majority of platforms you would wish to deploy to. It is almost a half-way between an interpreted language, and a compiled language, gaining the benefits of both.

Codemwnci
+2  A: 

You ask if one could write a "C VM". Not exactly. "Java" is a big term used by Sun to mean a lot of things, including both the programming language, and the virtual machine. "C" is just a programming language: it's up to the compiler and OS and CPU to decide what format the resulting binary should be.

C is sometimes said to be portable because it doesn't specify the runtime. The people who wrote your compiler were able to pick things that make sense for that platform. The downside is that C is low-level enough, and platforms are different enough, that it's common for C programs to work fine on one system and not at all on another.

If you combine the C language with a specific ABI, you could define a VM for it, analogous to the JVM. There are a few things like this already, for example:

  • The "Intel Binary Compatibility Specification" is an example of such an ABI (which almost nobody uses today)
  • "Microsoft Windows" could also be such an ABI (though a huge and underspecified one), for which Wine is one VM that runs programs written for it
  • "MS-DOS", for which dosemu is one VM
  • "Linux" is one of the more popular ones today, whose programs can be run by Linux itself, NetBSD, or FreeBSD
  • "PA-RISC", for which HP's Dynamo was a JIT-like VM

All of these C VMs are in fact a real machine -- nobody, AFAIK, has ever made a C VM that was purely virtual. This isn't surprising, since C was designed to run efficiently on hardware, so you might as well make it run normally on one system. As HP showed, you can still make a JIT to run the code more efficiently, even on the same platform.

Ken
Don't forget that WINE stands for Wine Is Not An Emulator!! No so sure if it should be called a VM.
teto
I haven't forgotten!! (That name change was originally suggested because of the first word, not the second: it was when Microsoft was in the process of trying to get the word "Windows" trademarked.) Doesn't WINE, after all, emulate Windows functionality? And isn't Java merely a compatibility layer on some platforms, e.g., picoJava? The line between these is a fine one, and I don't see reason to draw it around WINE, no matter how cute their acronym is.
Ken
+2  A: 

As others have already said, portability is somewhat of a fuzzy concept. From a certain perspective, C is actually more portable than Java. C makes very few assumptions about the underlying hardware. It doesn't even assume that there are 8 bits in a byte, or that negative numbers should be represented using two's complement. Theoretically, as long as you have a Von Neumann based machine and a compiler, you're good to go with C.

In fact, a "Hello world" program written in C is going to work on many more platforms than a "Hello world" program written in Java. You could probably get the same "hello world" program to work on a PDP-11 and an iPhone.

However, the reality is that most real-world programs do a lot more than output "Hello world". Java has a reputation for being more portable than C because in practice, it takes a lot more effort to port real-world C programs to different platforms than real-world Java programs.

This is because the C language is really ANSI-C, which is an extremely general-purpose, bare-bones language. It has no support for network programming, threading, or GUI development. Therefore, as soon as you write a program which includes any of those things, you have to fall back on a less-portable extension to C, like Win32 or POSIX or whatever.

But with Java, network programming, threading, and GUI tools are defined by the language and built into each VM implementation.

That said, I think a lot of programmers also underestimate the progress modern C/C++ has made in regard to portability these days. POSIX goes a long way towards providing cross-platform threading, and when it comes to C++, Boost provides networking and threading libraries which are basically just as portable as anything in Java. These libraries have some platform-specific quirks, but so does Java.

Essentially, Java relies on each platform having a VM implementation which will interpret byte code in a predictable way, and C/C++ relies on libraries which incorporate platform specific code using the preprocessor (#ifdefs). Both strategies allow for cross platform threading, networking, and GUI development. It's simply that Java has made faster progress than C/C++ when it comes to portability. The Java language spec had threading, networking and GUI development almost from day one, whereas the Boost networking library only came out around 2005, and C++0x is only just now finally getting portable threading.

Charles Salvia
great explanation.. thanks :)
Raze2dust