A couple of months ago I went back to the University. This time as a Part-time Assistant Professor teaching Programming Fundamentals to the next generation of software developers. I have been mostly focused on Java development projects for the past few years but the course was in C++. Not a big deal I thought.
Sure, they have pointers, but the concepts are the same. The syntax is very similar. How hard could it be to get back to C++? I haven’t been working with C++ since my BS graduation more than 10 years ago but I was confident. I know how to write code, I know how to solve problems.
I went back to a different world
Something I had forgotten, something I accepted as granted was about to hit me. Normally all you need to run your very simple “Hello world” application is having your code and using a compiler to turn it in executable binary. That binary is what your operating system (OS) is executing and your program is starting. So far so good.
I got a compiler suitable for my Windows version, I set up everything and I was ready to go. Then it came to the computers the students are going to use. As in every University, there are computer rooms with already installed and configured environments. Great I thought. Nothing to worry about.
A small issue hit me the very first practice – some students want to use their own laptops. Great. That way they will be able to have the code they have written all the time. Some pain was due until their local development environment is installed and setup, but nothing I haven’t gotten through several times when teaching Programming fundamentals with Java. They just needed the right compiler for their OS.
Then the unpredictable happened. A simple program was running perfectly with one compiler but transferred to a different environment with different compiler it had issues. Both compilers support the same C++ version but being built to compile code for different underlying architecture turns out to be the problem. Sure, the differences are small but they could cause issues. Instead of getting 10000 as a result of several multiplications, divisions and remainings in division, we got 9999. Most cases worked exactly the same but it differed in some without any apparent reason.
What happens if our program wasn’t a simple student application but an actual software product? If the code is supposed to be running in the same environment used during the development and testing – probably no issues would appear. But what if a client comes and says he wants the software running on a totally different platform? Is the assumption “it would probably work fine when installed on OS X” good enough?
In my experience, it’s far from it. In the best case, it will cause some increase in delivery cost due to the need for extensive testing and probably bug fixing due to the difference in the environment. In the worst-case, some bug will be found after the software is gone into production. The increase in cost there is usually a lot greater than if found during the development.
How Java solves the issues with compiler difference
That was the line of thought that made me realize how dangerous simple compiler difference could be. This was the time I once again appreciated the approach Java creators took to solve that problem. Instead of building a compiler that creates binary executable they created a compiler that transforms the code into so-called bytecode.
As this can’t be used directly by the OS, they created an interpreter – the Java Virtual Machine (JVM). It takes the bytecode created by the Java compiler and runs it – basically using it to give instructions to the operating system. Wait a minute. Wouldn’t it cause the same issues – each OS needs specific sets of commands?
It would but here the JVM is responsible on one hand to be built specifically for the underlying OS and hardware architecture, and on the other to run the bytecode generated by the compiler exactly the same way. This is the reason Java is considered architecture neutral language – execution doesn’t depend on the underlying OS and hardware.
For us, as developers, this is a great perk – no need to consider the environment our software products are going to run into. No worries what will happen when deployment needs to be done on some new OS or computer architecture. We can focus on the main task we have – build the best possible software product.
Project benefits for our customers
It eliminates the potential for issues and cost increases caused by deployment environments. It gives them the flexibility to choose the server based on the best fit both in terms of cost and reliability. Let’s not forget the ability to easily move from on-premises servers to cloud-based providers with a lot lower expectations for issues in that area.
As a part of every decision, having JVM is not without its downsides. Software applications written in Java are considered to be slower running than those written in C++ for example.
The reason being that you have an extra module that needs to operate. Practice, however, shows that in the majority of cases (business software, web-based products, backend API’s and many others) this is not a significant issue and benefits outways multiple times the downsides.
If you find this article interesting and want more like it, you can subscribe to our newsletter. There are plenty of interesting stories coming up.