Two Ways in Which Java Didn’t Get It

While Java is a very practical language, used nowadays to implement a large array of software applications, it also has its own share of problems. I am not the first and won’t be the last person to touch on the many issues raised by its design, especially in the areas of syntax and support for non-OO concepts.

While design problems are an interesting issue for technical discussion (especially if you are a programming aficionado), it is clearly not the main reason why someone would decide to use a language or not. Mostly, you have to answer pragmatic considerations such as “do you know how to use the language well?” and “does the language provide support for the type of problems I want to solve?”

Despite this, here I will consider only two of the design problems in Java that I haven’t seen discussed in other places.

Safety versus Performance

The first problem is related to the security focus of the language. As Java was initially sold as the language of the Internet, the fact that it was designed for safety looks like a very important issue. After all, nobody wants to download and install software that is unsafe and untrusted.

The mistake of Java, however, is that it tries to achieve safety at the level of byte-code execution, thinking that this is the most important aspect of security – or at least so important that it would be able to fix most of the security issues we might encounter in a networked world. For example, every time you load a Java class (or set of classes), the runtime mechanism has to spend a good amount of time trying to determine if the code is safe or not.

Security checks at the byte-code level take time and effort from the part of the runtime system. The big problem with this, however, is that only a small fraction of all code written in Java really needs the security checks that are in place. For example, even if you’re writing code that will never be in contact with the Internet, you still need to pay the price for this heightened level of security when using the Java runtime. The unintended consequence of such decisions is that the security system exists mostly to slow down the execution of programs, while complicating the class loading process.

Moreover, it is now understood that security at the programming language level is of very little importance for the safety of the overall system. If a malicious programmer wants to do something bad through a downloaded application, there are thousands of avenues that can be pursued, for example, by just getting enough information directly from the user. In most cases this can be done without even having to bother executing unsafe code.

That is why modern mobile applications are digitally signed: to make sure you know its origin. Trust, in the digital world as everywhere else, comes from knowing who created the code. It is part of a reputation system, not simply result of the analysis of the code itself. Moreover, with all the security measures imagined by its designers, Java turned out to become a big vector of malware infection. So much for the supposed safety offered by the language.

Over-Engineering the JVM

Another important innovation of Java is that it made the JVM, its virtual machine, the center of attentions. Unlike other languages that consider the description of the virtual machine simply as a detail that is hidden from users, Java decided to make it a public requirement for implementers, in order to guarantee the compatibility of code written at the JVM level and provide the Java-compatible seal.

While there are interesting advantages in using a well-defined set of operations interpreted by a virtual machine (for example, the ability to transfer compiled code over different architectures), the end result of this type of low-level focus is to bring unnecessary attention to specific areas, in detriment to the overall needs of the language. Java is nowadays certainly paying the price for these early decisions.

In a new language, the syntax and runtime system should be the main focus – not the virtual machine where the programs are executed. Case in point: the implementation of Javascript is constantly improving, with a performance that nowadays approaches (and sometimes exceeds) that of Java, at least for some application areas. The main reason is that designers of Javascript engines have fewer limitations on what they can do. In particular, they can improve the intermediate code as the execution engine matures and new approaches for optimization are necessary.

The same has been true for other interpreted languages, such as Smalltalk. But this natural evolution of the op-codes and other internal representations of compiled code cannot be easily achieved in Java, because the definition of the JVM over-specifies its execution mechanism. For example, it determines the exact representation of the compiled byte-codes. Therefore, even if a better way of representing and executing Java programs becomes available, it cannot be used by compliant virtual machines.

These are issues that may be seen as easy to overcome, but that in fact permeate the way the language is approached by users and implementers. Avoiding this is not possible for Java anymore, and programmers have to learn to live with the limitations of these early decisions, or look for better ways to express themselves. Either way, it is important to learn from past problems and avoid repeating them. Newer languages such as Javascript seem to have used a few of these lessons.

About the Author

Carlos Oliveira is a software engineer and the author of Objective-C Programmers Reference.

Related Books

Here are some other books on this topic:

The Pragmatic Programmer: From Journeyman to Master

Similar Posts:

About the Author

Carlos Oliveira holds a PhD in Systems Engineering and Optimization from University of Florida. He works as a software engineer, with more than 10 years of experience in developing high performance, commercial and scientific applications in C++, Java, and Objective-C. His most Recent Book is Practical C++ Financial Programming.

1 Trackback(s)

  1. Apr 15, 2016: Two Ways in Which Java Didn’t Get It | IT Rants

Post a Comment