Why choose Java?
Or as the lawyers will probably correct me, the question in the title would more accurately be phrased as "Why Choose the Java platform?". If you've been following my blog, you may notice that I haven't written in a while. This is because I've been really busy with my day job. One of the things that the job brought me on recently was a road trip to meet with some customers.
On this trip, I had the pleasure of having a conversation with an esteemed fellow embedded systems developer who was trying to understand the Java platform. He asked, "Why Java?". Such a simple question (simple only in its phrasing), but so pertinent. In his case, he was relatively new to Java, but has been doing embedded systems development for a long time. What he was asking was actually (1) why the Java platform is relevent for his projects (i.e. an embedded systems device), and (2) why he should choose it over available alternatives.
To be honest, I was a little caught off guard by this question. I had to pause for a while to think. On the spot, the only way I could think of to answer his question in the proper context was to tell him my personal story of how I came to choose the Java platform myself. This was the same event that motivated me to learn about the internals of a Java VM which got me hooked, and eventually led me to come work for Sun. I thought that the answer to this question that he asked may also be pertinent and interesting to other embedded systems developers who may not yet know of the advantages of the Java platform. So, I decided to share it with you here.
Complexity & Human Limitations
Before joining Sun, I used to work on an embedded system device that runs games that involve money. Hence, the device needs to be secure on many levels because of the money aspect. The security aspects (e.g. transactional programming, using redundancies, fault tolerance, etc.) require specialized domain specific knowledge in order to do things correctly in a secure way.
On the other hand, the product also needs to be open to a large population of developers in order to get more content (i.e. games) for it. It's not easy to find a lot of game developers who are competent enough to develop secure applications. So, I had a dilemma: how do I allow a lot of game developers to work on the software for this device without risking compromise to the security of the system? With the number of developers increasing, the chance of someone accidentally introducing stray pointers (or name your favorite bug) that compromises the system also increases.
And this is not strictly an issue of the competence of the game developers either. No matter good an engineer you are, everyone has bad days when they are tired (or sick or whatever), and makes mistakes. It would be nice if I knew for sure that the critical parts of the systems are protected from any mistakes I may make when I'm concentrating on game development (i.e. when I'm not thinking so much about the security aspect).
So, how did I seek to deal with this dilemma? The answer is ...
Use a Scripting Language
What I actually mean is: use a runtime interpreted scripting language. Let the content developers write their content with the scripting language instead of native code for the device. Using such a scripting language will give you these benefits:
The scripting language serves as an abstraction of the device. It only exposes
the APIs that the content developer needs. Critical code is not exposed, and is
therefore inaccessible to the content developer, thereby preventing any
intentional meddling with the critical code.
In additon, a scripting language can prevent the content developers from
doing any pointer manipulation. This solves the problem with stray pointers
that can unintentionally crash the system or interfere with the critical code.
Human Resource Options
You can afford to put more engineers on your project to develop the needed
content without having to train all of them to be experts in the critical
code. They don't need to know how to not compromise the critical code.
The scripting environment simply shields the critical code from them.
If desired, you can also outsource some content development or make a
software development kit (SDK) publicly available. Let other people develop
the content for your device without having to worry about their code
compromising your product e.g. crashing it, etc.
You also don't need to give them access to the source of critical code. The
scripting language and APIs are all they need. Note that, in some industries,
it is a requirement that critical pieces of code are not publicly viewable.
Without a scripting language abstraction, you may not have the
option to let external developers build content for your device.
A scripting language is "interpreted". With that, it is usually possible to
deploy more code into your device after the device has shipped. The code can
be deployed over a network or loaded from some removable media like a CD.
This feature has many uses. Here are some:
Deploying bug fixes: you can replace buggy modules in your device
without having to recall the devices. This helps improve customer
satisfaction, and reduce your field support costs. In the U.S., customer
dissatisfaction can mean (1) they will return your product i.e. loss of
present business, and (2) you'll get a bad reputation i.e. loss of future
business. Hence, this feature directly contributes to your profitability.
Sales of feature upgrades: you can develop
additional content that the customer can choose to purchase
over the network. This allows you to monetize your investment
beyond the initial sales of the device.
Conservation of resources: unused code modules can
be unloaded from memory. Only used content need to occupy
memory. This reduces your hardware cost in terms of memory
capacity needed. It can also improve your device power
consumption (for devices which need to be low powered).
By allowing you to operate in less RAM, you don't always have
to keep all RAM modules energized, thereby saving power.
Once I understood the benefits of this approach, I set about creating my own scripting language. However, in order for the content to be interesting, the scripting language needed to provide more and more functionality like that of a full programming language. After numerous enhancements to the script engine, eventually I realized that I am re-inventing a solution just like the Java programming language.
the Java platform as a Scripting Engine
But why use the Java platform instead of rolling your own? Well, here's why:
the Java platform is standardized
The specifications are publicly available from various sources. There
are many books / online resources / tutorials on how to develop on it. Hence,
it'll be easier to find developers who can be productive sooner.
There are also abundant resources to train new developers if
needed. You won't have to develop the training material on the
the Java platform is a mature technology
The Java platform has been around for a while and has been tested and
deployed in many industries. It is mature both in terms of implementation
as well as APIs. There's less risk that there's some bug in the platform
that poses security risks, or has some intrinsic flaw in its
Multiple vendors provides compliant implementations of the Java
platform (Sun isn't the only one). You can pick the one that best
fits your needs and development budget.
Availability of Development Tools
No need to write and maintain your own debugger. You can
buy one, and get on with developing and debugging your content,
instead of wasting time debugging the scripting engine and the
These days, most Java VM implementations come with good to state of
the art JIT technology that makes its "interpreted" code run at
compiled code speeds. You won't necessarily have the time nor
resources to develop equivalent technology for your own personal
There is a large community of companies and developers who are
continually working to improve the features and implementation
quality of the Java platform, and you get to benefit from their
efforts. You're on your own if you roll your own scripting
Future Proofing your Investment
One of the Java platform's greatest strengths is its
Write-Once-Run-Anywhere (WORA) goal. Yes, in practice, it is not perfect,
but there is still a lot of value in this. Simply put, your
investment in application code that you write today will not be
wasted in the future because they will still run in all future
versions of your products. Of course, a port of the Java platform
will be needed for your next generation devices. More on this
The Java programming language is a real programming language
complete with well-defined syntax and grammar. Developers can
actually write complex logic in it as expected from any programming
language. They aren't just limited to working with a canned set
of widgets that you provided script wrappers for. They can
actually add their own enhancements or custom widgets when needed.
The platform also comes with a rich set of APIs. This mean
developers spend less time writing support libraries, and more
time developing content for your product.
Of course, there are the usual benefits of programming with the
Java programming language and its APIs:
object-oriented paradigm - yeah, I know it's obvious,
but it's worth mentioning.
garbage collection - no more stray pointer problems.
classloading - you can dynamically deploy more code
after your device has been deployed.
multi-threading - threads are native in the Java
platform. If you need it, you can implement multi-threaded
solutions with ease.
robust security architecture - you can deployed
fine-grained security control if you want. No need to
re-invent your own, and risk inventing one that has security
networking - standard APIs allow you to do networking
It would take a lot of work for you to implement a platform with
the same amount of features, and to get it to the necessary level
of maturity and reliability for product deployment.
Why not use another scripting or interpreted technology?
The only other "interpreted" platform (that I know of) that comes close to the Java platform in terms of most of the above benefits is Microsoft's .NET. I thought it was a great testimony to the power of the Java platform that Microsoft had to develop a runtime interpreted platform of their own after seeing what the Java platform can do. The downside with .NET is that there is currently only one vendor for it i.e. Microsoft. Sure, there's the MONO project which is owned by Novell now, I think. I don't know how complete the MONO implementation is at present. In general, your vendor choices are far more limited than with the Java platform.
Some of these are not as mature as the Java platform.
Lack of a community of developers to support them (for some).
Features (e.g. multi-threading, security architecture) may be lacking
Lack of APIs. They usually don't come with a rich set of
standard APIs like the Java platform.
Performance may not be as good because most of these are executed using
text-based interpretation, which is a lot slower than Java bytecode interpretation
let alone Java JIT technology.
Development tools (e.g. debuggers) may be rare or not available for them.
In fact, this is one of the most common complaints from developers who have
to work with these technologies.
Less availability of engineers trained in most of these languages. This
one is just my guess, but I have read survey results which show that the Java
programming language is among the top most popular languages among developers
today (ranked first or second depending on which survey). The other most popular
language is C/C++. The rest of these are much lower in popularity and developer
What is certain is that none of them have all the advantages of the Java platform in a single package. Certainly, you can enhance these technologies and eventually get to where the Java platform is. But if you're not a platform developer, I'm guessing that you would be much more interested in getting on with your product development than having to enhance the platform that you build your products on.
At the end of the day, your product is what makes money for you. The platform that it is built on does not (at least not in an immediate sense). Hence, it makes more sense that you should invest your time on your product instead of trying to upgrade an immature platform. Note that this is also a major reason why the Java platform is preferable over rolling your own scripting language.
Future proofing your investments means to ensure that it does not lose its value significantly over time. Let's consider a few scenarios of how this issue is relevant to your product development:
Cost of Components
Over time, more powerful hardware becomes cheaper. Alternatively,
other OSes become more viable or cheaper to license. Hence, you
may be interested in implementing the next generation of your
product on this new CPU/OS. Ideally, you would want to be able
to reuse the majority of your existing software to minimize
Different Hardware Class Offerings
When a product is successful, you may want to offer alternate
class of the same product at different price points to maximize your market. For
example, a low-end, mid-range, and high-end class of your
products each with a different underlying CPU/OS. The use of
different CPU/OS is not by choice but rather, is driven by the
cost budget and capabilities of each of the class of devices.
However, even though the hardware may vary, ideally, you would
want most of your software to be able to run on all of them.
A hardware part may cease to be offered by the manufacturer.
Hence, you may be forced to do a hardware re-design. Since
hardware re-designs are expensive processes anyway, you might
want to take the opportunity to change other components as well
either for cost reduction or feature enhancements. Regardless
of the changes, you will still want the majority of your
existing software base to just work on the new hardware.
These scenarios are not uncommon in the embedded systems world. They are examples of when there may be a good reason to change the underlying hardware that powers your device. Yet, in all these cases, you would want to minimize your cost. Software development is definitely one of the greatest costs in any embedded system development effort. With the Java platform's WORA characteristic, the majority of your software (the parts that are written in the Java programming language) are reusable on your new hardware.
Of course, this reuse isn't entirely free. You will need a new port of the Java platform for your new device. However, the effort to port a Java platform will be significantly less than the effort to port all your code if they were not written in a platform independent language like the Java programming language. There are more details about this in the section below.
Why not use a native solution?
Certainly, with C/C++ and Linux, you can have a lot of the features that you get with the Java platform. There are a lot of developers who know C/C++ and Linux. There are a lot of development tools available. You can even get the upgradeability feature using shared libraries. Well, the downside is:
You'll have the same stray pointer problems you started with. And,
You won't have the option to let 3rd party developers work on your
content software due to security or quality risks.
Higher Development Cost
In the event that you have a need to introduce new hardware, you
will need to at least recompiled all your code for the new device.
And you will also need to re-test your code on the new device.
In addition, for each new piece of content software that you
develop, you will have to compile the new software for and test
on all your device flavors. This increases development time
Deployment & Maintenance Cost
Let's say you have a network server that allows your device to
download bug fixes or software upgrades for purchase by users.
You will now need to keep a different version of each software
for each device type. Managing and tracking all the different
versions adds to your deployment costs.
When you need to do a bug fix, you will need to compile and
test the bug fix for all device architectures, and deploy all
versions on your server. This increases your maintenance cost.
But wait a minute. With the Java solution, don't you have to port and retest the Java implementation as well? Yes, you do. But the porting cost is reduced because it is confined only to the Java platform as opposed to your entire code base. Also, with the large Java developer community, there may already be a port to the new hardware (especially if you are using standard hardware). All these factors will lessen your porting cost also.
What about testing? With the Java platform, there are standard test suites that check for API conformance i.e. they test the API signatures, as well as their expected behavior. They also test the VM's behavior. These tests are known as the Technology Compliance Kits (TCKs). TCKs are available to licensees of Java technology.
However, the TCKs are not exhaustive tests in terms of code coverage. In addition, Sun has other elaborate testsuites that we use internally to stress test the quality of our Java implementations beyond what is covered by the TCKs. If you want to, you can contract with Sun's Engineering Services (or any other big Java platform implementor who has this offering) to do these tests for you to ensure that your new Java implementation port is compliant, robust, and behaving as you expect it to. Yes, it does cost some money. But at least you have the option if you want it.
The Costs of a Native Solution
Consider the alternative of developing on C/C++ and Linux directly. Note that C/C++ compilers have been known to have bugs or differences as well. For example, some floating point implementations may have rounding problems. Or the floating point behavior on different CPUs may do rounding slightly differently. These difference will often go unnoticed. The only reason we knew about them is because our TCKs caught them when our VM ports are built for different CPUs. You will care about this if your software happens to depend on certain behaviour that happened to change when you moved to a new CPU. This means that to be sure, you will really have to test all your software on all your device flavors.
A similar issue goes for Linux (or whatever OS you are using). What compliance tests are there to ensure that the OS will behave in exactly the same way such that you can expect your existing software to work correctly when they are re-compiled for the new device? Usually, there are none.
With a Java implementation, you can reduce the testing cost, and do it effectively by only testing at the Java platform level. You also have the option to get help in testing it if you don't have the time to do it yourself, or want added confidence in the quality of the port. These options do not exist for using a direct to native solution. You may still test some of your software applications on your various device flavors for added confidence, but you won't need to test all variations in order to achieve a high level of confidence because of the conformance of the Java implementation port.
What about Legacy Code?
You may already have a lot of legacy code from previous products. Do you have to re-implement all of this in the Java programming language immediately if you were to deploy your new system on the Java platform? The answer is no. You should re-implement the parts that make sense, and would yield benefits from being implemented in the Java programming language. The remaining bits can be accessed through the Java Native Interface (JNI). Hence, you can choose to pay the price of porting the legacy code only when it would yield gains or is meaningful for you. This porting strategy allows you to reduce time to market for your new device as well as reduce unnecessary up-front development cost in terms of porting.
Of course, there are natural benefits to having all of the code implemented in the Java programming language (as explained above). If this option is available to you, you may want to seriously consider it. Or alternatively, you can plan a strategy to do the porting of legacy code gradually over time so as to amortize the cost of doing so over many product releases.
In the above, I've explained why it makes sense both from a technical and business sense to implement your product on the Java platform. Of course, it would be incorrect for me to say that the Java platform is suitable for all embedded systems development. There can always be exceptions, but in general, the platform does offer many benefits in this space and should be considered seriously.
Of course, when it comes to embedded development, there can also be other issues like real-time characteristics, thread priority issues, etc. Generally, none of these issues should make it prohibitive for you to deploy your product on the Java platform. As for the details, I will leave that for another article and another day.
Hence, the conclusion for today is: you should choose the Java platform because it makes sense to do so. :-)