How java solved portability? - java

Java compiler converts Java code to bytecode and then JVM converts bytecode to machine instructions. As far as I have understood, JVM are built for different platforms (processor + OS). Then how can we say that Java is platform independent? Ultimately, we require a JVM which is platform dependent?

As you have mentioned yourself, JVM is platform-dependent. That's it - JVM is platform-dependent, but not JAVA. After all, the JVM needs to be run in someway inside the native machine, so it must have to be specific to that platform.
JAVA is portable in the sense that the compiled code is portable. For example, if you compare with C, both the C and Java source codes are portable, that means both of them provide source code portability. Once you have a source code written in a Windows PC, you can transfer that exact code in another Linux machine and both Java and C code will compile and run fine in both machines.
But, what about object code portability?
We know, when we compile a C code, it produces the machine readable object code. So, if you compile a C source code from one machine, then that object code may not be run from another machine if they are not compatible. But, in case of JAVA, if you compile a Java source code to bytecode from one machine, that bytecode can be run in any machine that runs the JVM.
Another interesting fact, by successful compilation of a Java source code, we are also producing a byte code for some unknown future CPU which doesn't even exist as JVM acts as a kind of virtual CPU.

The end-user writes code in java and that is platform independent.
The JVM engineer works on creating the JVM and the JRE and within it the compiler and the interpreter for different platforms. Therefore that absolves the end-user to worry about porting their codebase to different platforms. Write once and then run it on all platforms (as long as there is a JVM available for that platform).
So from the perspective of the end-user (Java programmer) the java code is indeed platform independent since it can run anywhere without any changes. Even though the JVM is ported to different platforms and is indeed platform dependent.
Difference with C/C++:
As it is with the JVM, there exists a C/C++ compiler for each platform responsible for translating source to machine/processor instructions. These machine instructions are understood by the processor, for instance: intel etc. Therefore a C/C++ compiler is made available for each platform it supports. However, you might need to link to specific OS/platform specific libraries in your program. That will make your program platform specific and will need to be rewritten for another platform by linking to that platform's version of that library. That becomes C/C++ programmer responsibility. Also each C/C++ compiler has its own vagaries specific to a platform unlike a JVM which provides a consistent view across platforms detailed below.
In case of Java, you are removed from tapping into platform specificities (unless the JVM or Java libraries do not provide it but they usually cover most of the basics). The java code taps into JVM and Java libraries and the JVM is responsible for translating that to bytecode or to machine instructions (to improve performance) at runtime. Unless you use JNI in your java source, you do not have to worry about portability. For instance: within your Java program, you can access the native environment, the host memory, some OS characteristics etc., and your code is still portable. The JVM provides the infrastructure in that the native calls to extract that information specific to the platform. However there might be some platform specific functionality that your java program requires that is not provided by the JVM or Java libraries and therefore you need to JNI and your portability suffers as a result.
Note: C/C++/Java all have source code portability. But what the JVM provides is binary portability. The compiled or interpreted java code runs on an abstraction called the JVM (Virtual Machine). The java programmer writes to that interface instead of the platforms that the JVM runs on. There is a clear separation here.

Related

Why do we use the Java virtual machine? [duplicate]

This question already has answers here:
Why a virtual machine is needed execute a java program.? [duplicate]
(3 answers)
Closed 2 years ago.
I am trying to wrap my head around the Java Virtual Machine and why it uses bytecode. I know it has been asked so many times, but somehow I couldn't finally make the correct assumption, so I researched many things and decided to explain how I think it works and if it's correct.
I understand that in C++, compiler compiles the source code on the specific (architecture + operating system). So, compiled version of C++ for (x86 + Windows) won't run on any other architecture or operating system.
My assumptions
When Java compiler compiles the source code into bytecode, It doesn't do the compilation depending on architecture or operating system. The source code will always be compiled to the same bytecode if it's compiled on Windows or Mac. Let's say we compiled and now, send the bytecode to another computer (x86 + windows). In order for that computer to run this bytecode, It needs JVM. Now, JVM knows what architecture + operating system it's running on. (x86 + windows). So, JVM will compile bytecode to x86 + Windows and it will produce machine code which can be run by the actual computer now.
So, even though we use Java Virtual Machine, we still run the actual machine code on our operating system and not on the virtual machine. Virtual Machine just helps us to transform bytecode into machine code.
This means that when using Java, the only thing we have to worry about is installing JVM and that's it.
I just always thought that the Virtual Machine is just a computer itself where it would run the code in its own isolated place, but in case of JVM, i don't think that's correct, because I think machine code JVM produces still has to be run on the actual operating system we have.
Do you think my assumptions are correct?
When Java compiler compiles the source code into bytecode, It doesn't do the compilation depending on architecture or operating system. The source code will always be compiled to the same bytecode if it's compiled on Windows or Mac.
All correct.
Let's say we compiled and now, send the bytecode to another computer (x86 + windows). In order for that computer to run this bytecode, It needs JVM. Now, JVM knows what architecture + operating system it's running on. (x86 + windows). So, JVM will compile bytecode to x86 + windows and it will produce machine code which can be run by the actual computer now.
This is mostly correct, but there are a couple things that are a bit "off"
First of all, to execute the bytecodes on any computer you need a JVM. That includes the computer on which you compiled the bytecodes.
(It is theoretically possible that a computer could be designed and implemented to execute the JVM bytecode instruction set as its native instruction set. But I don't know if anyone has ever seriously contemplated doing this. It would be pointless. Performance would not be comparable with hardware that you can by for a couple of hundred dollars. The JVM bytecode instruction set is designed to be compact and simple, and it is relatively easy to JIT compile. Not to be executed efficiently.)
Secondly a typical JVM actually operates in two modes:
It starts out executing the bytecodes in software using an interpreter.
After a bit, it selectively compiles bytecodes of heavily used methods to the platform's native instruction set and executes the native code. The compilation is done using a JIT compiler.
Note that the JIT compiler is platform specific.
So, even though, we use Java Virtual Machine, we still run the actual machine code on our operating system and not on the virtual machine.
That is correct.
[The Java] Virtual Machine just helps us to transform bytecode into machine code.
The JVM actually does a lot more. Things like:
Garbage collection
Bytecode loading and verification
Implementing reflection
Providing native code methods for bridging between Java classes and operating system functionality
Implementing infrastructure for monitoring, profiling, debugging and so on.
This means that when using Java, the only thing we have to worry about is installing JVM and that's it.
Yes. But in a modern JDK there are other alternatives; e.g. jlink will generate an executable that has a cut-down JRE embedded in it so that you don't need to install a JRE. And GraalVM supports ahead of time (AOT) compilation.
I just always thought that the Virtual Machine is just a computer itself where it would run the code in its own isolated place, but in case of JVM, i don't think that's correct, because I think machine code JVM produces still has to be run on the actual operating system we have.
Ah yes.
The term "virtual machine" has multiple meanings:
A Java Virtual Machine "executes" Java bytecode ... in the sense above.
A Linux or Windows virtual machine is where the user's application and the guest operating system are running under the control of a "hypervisor" operating system. The applications and guest OS use the native hardware to execute instructions, but they don't have full control of the hardware.
And there are potentially other shades of meaning.
If you conflate JVMs with other kinds of virtual machine, you can get yourself in knots. Don't. They are different enough that conflating the concepts in not going to help you understand.
When compiling java code, java-bytecode is created.
This bytecode is platform independent and can be run by the JVM. This means that other programming languages like Kotlin can also generate this java-bytecode and target the JVM.
So you are correct about the java-bytecode being the same for every platform.
Where you aren't entirely correct however is, that the JVM converts the java-bytecode to native bytecode.
The JVM executes the java-bytecode instead and gives the instructions to the operating system. While executing, the JVM compiles bunches of java-bytecode to native code, which the operating system can then execute. This happens while the code is executed so a class that is never loaded will also never be executed and will never end up as machine code.
Due to this we can use features like Reflection where some of the java-bytecode of a class files can be modified at runtime before being compiled to native machine code.
The JVM basically sits between the operating system and the java-bytecode. In some sense just like a normal VM.
The article below has a nice visualization of the JVM.
https://www.guru99.com/java-virtual-machine-jvm.html
The java byte code is a form of intermediate code.
That code can be interpreted, a JVM is such an interpreter emulating (simulating) every single byte code instruction. This is slow but easily portable.
That code can be compiled to native code, normally a JVM contains a just-in-time compiler for code that is indeed executed. This native code can be optimized for the current machine it is running on, and the native code does not need to be loaded from file, and code inlining can be done.
So the JVM principly is a turbo-charged interpreter, of java byte code, portable to many platforms.
Context:
[Other languages] Microsoft's C# language is more of a compiler.
[Other intermediate codes] LLVM IR is an intermediate code from the C side, compilable.
[Other JVMs] There are more than one JVM, with different techniques.

What does platform independent languages really mean?

Why isn't C/C++ called platform independent like java when the same source code written in C/C++ can be made to run on different operating systems by different compilers, just like JVM is used in java.
Isn't different compilers and JVM doing same thing and achieving platform independence.
Isn't different compilers and JVM doing same thing and achieving platform independence.
Not really. Your Java program is running within the JVM, which acts as a translation layer between the Java byte code and the native machine code. It hides the platform-specific details from the Java application code.
This is not the case with C. C code (typically) runs natively, so there is no translation layer isolating it from platform-specific details. Your C code can be directly affected by platform-specific differences (word sizes, type representations, byte order, etc.).
A strictly conforming C program, which uses nothing outside of the standard library and makes no assumptions about type sizes or representation beyond the minimums guaranteed by the language standard, should exhibit the same behavior on any platform for which it is compiled. All you need to do is recompile it for the target platform.
The problem is that most useful real-world C and C++ code isn't strictly conforming; to do almost anything interesting you have to rely on third-party and system-specific libraries and utilities, and as soon as you do you lose that platform independence. I could write a command-line tool manipulates files in the local file system that would run on Windows and MacOS and Linux and VMS and MPE; all I would need to do is recompile it for the different targets. However, if I wanted to write something GUI-driven, or something that communicated over a network, or something that had to navigate the file system, or anything like that, then I'm reliant on system-specific tools and I can't just rebuild the code on different platforms.
It's not the language itself that is platform dependent. It's possible to compile both C and C++ for JVM, but it's not very common to do so. Compiling C++ for the JVM
In the same way, it is possible to compile Java for a specific target instead of JVM. Compiling java source code to native exe
But Java and JVM are both designed to work together, so that combination is very natural to use.
C is designed to be very close to the hardware. There's not really a reason to use C if your target is JVM. Then use Java instead.
In theory, you can compile ANY language for ANY target, as long as the target is turing complete.
Sidenote: Don't write "C/C++". They are completely different languages.
In case of C or C++ (language that are not platform independent), the compiler generates an .exe file which is OS dependent. When we try to run this .exe file on another OS it does not run, since it is OS dependent and hence is not compatible with the other OS.
Isn't different compilers and JVM doing same thing and achieving platform independence.
The JVM per se is the platform. It is abstracting away, whether it is ARM/AMD64/...
C/C++ is getting compiled. It may only run on the processor(family) that it was compiled for.
You can't just take a binary for MIPS and execute it on ARM.
Compare it:
[C(++)]
|
v
[Processor]
vs
[Java (Classfiles)]
|
v
[JVM] #Abstraction layer
|
v
[Processor]
The role of JVM in the independent platform is that it acts as a virtual processor. when we used c/c++ to compiler different processor converts the source code into a different binary pattern that's why there are not platform-independent.
C++ language itself doesn't assume any specific platform, so in that sense it is platform independent.

Does the Java interpreter convert the byte-code files to an executable file?

I had this question in software course:
True/False: The Java interpreter converts files from a byte-code format to executable files.
I think the statement is false. In class, they said the interpreter "executes" the byte-code files, on the system using the JVM (I didn't listen too much but I think I got it fairly correctly), but as I understood, it doesn't actually convert it to executable files (which presumably are .exe files), just runs it on the system directly.
"True/False: The Java interpreter converts files from a byte-code format to executable files".
The answer is false1.
The Java interpreter is one of the two components of the JVM that is responsible for executing Java code. It does it by "emulating" the execution of the Java Virtual Machine instructions (bytecodes); i.e. by pretending to be a "real" instance of the virtual machine.
The other JVM component that is involved is the Just In Time (JIT) compiler. This identifies Java methods that have been interpreted for a significant amount of time, and does an on-the-fly compilation to native code. This native code is then executed instead of interpreting the bytecodes.
But the JIT compiler does not write the compiled native code to the file system. Instead it writes it directly into a memory segment ready to be executed.
Java's interpret / JIT compile is more complicated, but it has a couple of advantages:
It means that it is not necessary to compile bytecodes to native code before the application can be run, which removes a significant impediment to portability.
It allows the JVM to gather runtime statistics on how the application is functioning, which can give hints as to the best way to optimize the native code. The result is faster execution for long-running applications.
The downside is that JIT compilation is one of the factors that tends to make Java applications slow to start (compared with C / C++ for example).
1 - ... for mainstream Java (tm) compilers. Android isn't Java (tm)2. Note that the first version of Java was interpreter only. I have also seen Java (not tm) implementations where the native code compilers were either ahead-of-time or eager ... or a combination of both.
2 - You are only permitted by Oracle to describe your "java-like" implementation as Java(tm) if it passes the Java compliance tests. Android wouldn't.
The Java compiler converts the source code to bytecode. This bytecode is then interpreted (or just-in-time-compiled and then executed) by the JVM. This bytecode is a kind of intermediate language that has not platform dependence. The virtual machine then is the layer that provides system specific functionality.
It is also possible to compile Java code to native code, a project aiming this is for example the GCJ.
To answer your question: no, a normal Java compiler does not emit an executable binary, but a set of classes that can be executed using a JVM. You can read more about this on Wikipedia.
False for regular JVMs. No executable files are created. The conversion from bytecode to native code for that platform takes place on the fly during execution. If the program is stopped, the compiled code is gone (was in memory only).
The new Android JVM ART does compile the bytecode into executables before to have better startup and runtime behavior. So ART creates files.
ART straddles an interesting mid-ground between compiled and interpreted code, called ahead-of-time (AOT) compilation. Currently with Android apps, they are interpreted at runtime (using the JIT), every time you open them up. This is slow. (iOS apps, by comparison, are compiled native code, which is much faster.) With ART enabled, each Android app is compiled to native code when you install it. Then, when it’s time to run the app, it performs with all the alacrity of a native app. http://www.extremetech.com/computing/170677-android-art-google-finally-moves-to-replace-dalvik-to-boost-performance-and-battery-life
The answer is false
reason:
JIT-just in time compiler and java interpreter does a same thing in different way but as per performance JIT wins. The main task is to convert the given bytecode into machine dependent Assembly language as of abstract information.Assembly level language is a low level language which understood by machine's assembler and after that assembler converts it to 01010111.....

How does Java bytecode deal with multiple platforms?

For example, let's say you have a java program that simply opens a window. This will obviously result in different assembly code for different operating systems (on windows it will eventually have to call CreateWindowEx). So how does the Java bytecode (or any other similar language) represent something platform specific like this?
The JVM is OS-dependent, byte code isn't.
This means that bytecode is a sort of "generic" language that JVM will interpret end execute according to the system it's running on.
UPDATE
As Chris Jester-Young says, my answer is not strictly correct:
The bytecode for a 100% pure Java program is indeed platform-independent. The underlying Java platform classes that such programs invoke are, of course, not.
Most of the time, the JVM will also JIT compile, not just interpret. (You can enable pure-interpretation mode, but it'll be slow!)
Serenity said this:
Typically, the compiled code is the exact set of instructions the CPU requires to "execute" the program. In Java, the compiled code is an exact set of instructions for a "virtual CPU" which is required to work the same on every physical machine.
So, in a sense, the designers of the Java language decided that the language and the compiled code was going to be platform independent, but since the code eventually has to run on a physical platform, they opted to put all the platform dependent code in the JVM.
This requirement for a JVM is in contrast to your Turbo C example. With Turbo C, the compiler will produce platform dependent code, and there is no need for a JVM work-alike because the compiled Turbo C program can be executed by the CPU directly.
With Java, the CPU executes the JVM, which is platform dependent. This running JVM then executes the Java bytecode which is platform independent, provided that you have a JVM availble for it to execute upon. You might say that writing Java code, you don't program for the code to be executed on the physical machine, you write the code to be executed on the Java Virtual Machine.
The only way that all this Java bytecode works on all Java virtual machines is that a rather strict standard has been written for how Java virtual machines work. This means that no matter what physical platform you are using, the part where the Java bytecode interfaces with the JVM is guaranteed to work only one way. Since all the JVMs work exactly the same, the same code works exactly the same everywhere without recompiling. If you can't pass the tests to make sure it's the same, you're not allowed to call your virtual machine a "Java virtual machine".
Of course, there are ways that you can break the portability of a Java program. You could write a program that looks for files only found on one operating system (cmd.exe for example). You could use JNI, which effectively allows you to put compiled C or C++ code into a class. You could use conventions that only work for a certain operating system (like assuming ":" separates directories). But you are guaranteed to never have to recompile your program for a different machine unless you're doing something really special (like JNI).
Source: How is Java platform-independent when it needs a JVM to run?
In the Java programming language, all source code is first written in plain text files ending with the .java extension. Those source files are then compiled into .class files by the javac compiler. A .class file does not contain code that is native to your processor; it instead contains bytecodes — the machine language of the Java Virtual Machine1 (Java VM). The java launcher tool then runs your application with an instance of the Java Virtual Machine.
please read this doc by oracle
.class files(i.e byte code) are same but not the JVM ,It differs with OS.
There are different Java Virtual Machine binaries for each operating system. They can run the same Java bytecode (classes, jars), but the implementations is sometimes different.
For example, all the window handling code is implemented differently on Windows, Unix and Mac. Each of them will call the OS native calls to open a window or to draw something. You don't have to care about it, because the Virtual Machine automatically does it.

Why is Java platform independent in theory and platform dependent in practice?

I know that one of the big things about Java is that it is platform independent in the sense that you can make a Java application and have it run in Windows, Linux, Mac, and so forth, as long as you don't use libraries specific to one OS, and as long as you have a JVM installed for the appropriate OS to interpret things correctly...
However, why can't a normal computer Java program (as in a simple Hello World in Java, for Windows or Linux for example) run just the same in a mobile phone, when mobile phones also have their specific JVM installed to interpret things correctly?
Why is it necessary to change the architecture of the program in some cases, such as Android development, or use Java ME to make applications specific for some general mobile phones?
I know that there are some functions that are related to certain functionalities of the OS, that might not apply in the mobile platforms for example, such as some things related with console, input methods, and so forth, but is this really the only reason that makes things not compatible? If so, why won't a simple application that just declares and initializes an integer variable be able to run across all non-mobile and mobile platforms that have a JVM available?
I am aware of other questions that have been posted before, such as this, but that do not focus the exact point I am aiming for here.
The unit of portability to look at is a class rather than an application. A class that declares and initialises an integer variable will run on all the platforms you describe, and many others too. They understand the same bytecode, even if they do execute it using different mechanisms ranging from bytecode interpreters, to JIT compilation, to Android's Dalvik (which translates JVM bytecode into its own instruction set).
Even if we look beyond a single integer variable, Java that uses "core" functionality will work on most of these devices. There's a great deal of common ground between J2ME, Android and J2SE (and particularly the latter two - J2ME was intended as a cut-down version of the standard Java APIs for devices with limited resources, so less of the standard API is available).
On a Windows/Mac/Linux system, an application is usually something that you explicitly start, use, and - when you're done - tell it to exit. Compare this with, say, an Android phone: the application might be started in response to an event occurring (perhaps an incoming SMS, or a specific type of file downloaded from the web) in which case it needs to know how and why it was started - a simple public static main(String[] args) just doesn't cut it. Once started, the app needs to be aware of events such as "low battery" or "entering standby mode" in order to free up resources or disable CPU-intensive features (such as GPS) that might otherwise drain the battery.
These aren't obscure functions - they're essential to a phone being useful as a phone - so all native applications must handle them.
When Java Code is compiled a byte code(class file) is generated which is independent of the system. This byte code is fed to the JVM (Java Virtual Machine) which resides in the system. Since every system has its own JVM, it doesn't matter where you compile the source code. The byte code generated by the compiler can be interpreted by any JVM of any machine. Hence it is called Platform independent Language.
thanks
Why is Java platform independent in theory and platform dependent in practice?
Remember and clear one thing that only the Java language is platform independent and try to understand the meaning of the sentence. Java is platform independent means the code you have developed using Java can be run on any machine.
When you compile the .java file it generates .class file and it contains bytecode and this bytecode is platform independent you can run it on any machine this is what about platform independency of Java language.
Now you said that it is not in practice so the reason is only Java language is platform independent, but its runtime enviroment, or JVM, is platform dependent, it is written separately for each OS. So we can say the Java language is platform independent, but its runtime environment is platform dependent.
The java language is just one thing but then many other devices such as mobile phones run their own version which is usually a trimmed down version to fit on the device. THese can also occasionally have other proprietary classes to help access the hardware (ie touchscreen). By making separate platforms based off a main one you get much support and a tighter more efficient programming language.
Sun micro systems has released different versions of jdk. one for windows based and another for linux/unix based. When we installed jdk with that we get jvm,jre and javac. Suppose if we write a java program in windows with intel processor which is installed with windows jdk, then the java compiler of that jdk will convert .java file to .class file which contains byte code instructions similar to assembly language code these byte code instructions can be understandable only by jvm. If we take the .class file which is generated in windows o.s and if we run in linux then the jvm of that linux machine internally rewrites your java program by using the approximate 200+ instruction sets which are developed by javasoft people and placed as part of jvm. and the .class file gets executed. So here the point is to concentrate that jdk is platform dependent but .class is not platform dependent it is platform independent because jvm only responsible for running any .class files. Every jdk's jvm internally has predefined instructions sets i.e., approx. 200+.

Categories